diff --git a/.github/ISSUE_TEMPLATE/01_installation.prolem.yml b/.github/ISSUE_TEMPLATE/01_installation.prolem.yml index eddcf6c8..6348c629 100644 --- a/.github/ISSUE_TEMPLATE/01_installation.prolem.yml +++ b/.github/ISSUE_TEMPLATE/01_installation.prolem.yml @@ -1,7 +1,7 @@ name: "🙏🏻 Installation Problem" description: "Report an issue with installation" title: "Installation Problem" -labels: ["installation"] +labels: ["type: installation"] body: - type: markdown attributes: @@ -13,4 +13,7 @@ body: attributes: label: For installation issues, please visit our https://discord.postiz.com for assistance. description: For installation issues, please visit our [Discord Support](https://discord.postiz.com) for assistance. - placeholder: For installation issues, please visit our https://discord.postiz.com for assistance. \ No newline at end of file + placeholder: | + For installation issues, please visit our https://discord.postiz.com for assistance. + Please do not save this issue - do not submit installation issues on GitHub. + diff --git a/README.md b/README.md index 37a882c3..2120df3c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,14 @@ +

+ Please help us out on Product Hunt,
to give you the best open-source
social media scheduling tool in the world 🌎👇

+Postiz - Your ultimate AI social media scheduling tool  | Product Hunt +

+

+

- Novu Logo + Postiz Logo

@@ -58,22 +64,6 @@
- -

-


-

We participate in Hacktoberfest 2024! 🎉🎊

-

We are sending a t-shirt for every merged PR! (max 1 per person)

-

Rules:

- -

-


-

-

diff --git a/apps/backend/src/api/routes/integrations.controller.ts b/apps/backend/src/api/routes/integrations.controller.ts index a394fe51..e19e8668 100644 --- a/apps/backend/src/api/routes/integrations.controller.ts +++ b/apps/backend/src/api/routes/integrations.controller.ts @@ -1,5 +1,12 @@ import { - Body, Controller, Delete, Get, Param, Post, Query, UseFilters + Body, + Controller, + Delete, + Get, + Param, + Post, + Query, + UseFilters, } from '@nestjs/common'; import { ioRedis } from '@gitroom/nestjs-libraries/redis/redis.service'; import { ConnectIntegrationDto } from '@gitroom/nestjs-libraries/dtos/integrations/connect.integration.dto'; @@ -22,7 +29,11 @@ import { PostsService } from '@gitroom/nestjs-libraries/database/prisma/posts/po import { IntegrationTimeDto } from '@gitroom/nestjs-libraries/dtos/integrations/integration.time.dto'; import { AuthService } from '@gitroom/helpers/auth/auth.service'; import { AuthTokenDetails } from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface'; -import { NotEnoughScopes } from '@gitroom/nestjs-libraries/integrations/social.abstract'; +import { + NotEnoughScopes, + RefreshToken, +} from '@gitroom/nestjs-libraries/integrations/social.abstract'; +import { timer } from '@gitroom/helpers/utils/timer'; @ApiTags('Integrations') @Controller('/integrations') @@ -51,7 +62,7 @@ export class IntegrationsController { id: p.id, internalId: p.internalId, disabled: p.disabled, - picture: p.picture, + picture: p.picture || '/no-picture.jpg', identifier: p.providerIdentifier, inBetweenSteps: p.inBetweenSteps, refreshNeeded: p.refreshNeeded, @@ -201,11 +212,51 @@ export class IntegrationsController { } if (integrationProvider[body.name]) { - return integrationProvider[body.name]( - getIntegration.token, - body.data, - getIntegration.internalId - ); + try { + const load = await integrationProvider[body.name]( + getIntegration.token, + body.data, + getIntegration.internalId + ); + + return load; + } catch (err) { + if (err instanceof RefreshToken) { + const { accessToken, refreshToken, expiresIn } = + await integrationProvider.refreshToken( + getIntegration.refreshToken + ); + + if (accessToken) { + await this._integrationService.createOrUpdateIntegration( + getIntegration.organizationId, + getIntegration.name, + getIntegration.picture!, + 'social', + getIntegration.internalId, + getIntegration.providerIdentifier, + accessToken, + refreshToken, + expiresIn + ); + + getIntegration.token = accessToken; + + if (integrationProvider.refreshWait) { + await timer(10000); + } + return this.functionIntegration(org, body); + } else { + await this._integrationService.disconnectChannel( + org.id, + getIntegration + ); + return false; + } + } + + return false; + } } throw new Error('Function not found'); } @@ -352,7 +403,9 @@ export class IntegrationsController { } if (refresh && id !== refresh) { - throw new NotEnoughScopes('Please refresh the channel that needs to be refreshed'); + throw new NotEnoughScopes( + 'Please refresh the channel that needs to be refreshed' + ); } return this._integrationService.createOrUpdateIntegration( diff --git a/apps/frontend/public/no-picture.jpg b/apps/frontend/public/no-picture.jpg new file mode 100644 index 00000000..7a8a8432 Binary files /dev/null and b/apps/frontend/public/no-picture.jpg differ diff --git a/apps/frontend/src/components/launches/add.edit.model.tsx b/apps/frontend/src/components/launches/add.edit.model.tsx index 14e3bfd3..58b4c4cf 100644 --- a/apps/frontend/src/components/launches/add.edit.model.tsx +++ b/apps/frontend/src/components/launches/add.edit.model.tsx @@ -49,6 +49,15 @@ import { CopilotPopup } from '@copilotkit/react-ui'; import { useUser } from '@gitroom/frontend/components/layout/user.context'; import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; import Image from 'next/image'; +import { weightedLength } from '@gitroom/helpers/utils/count.length'; + +function countCharacters(text: string, type: string): number { + if (type !== 'x') { + return text.length; + } + + return weightedLength(text); +} export const AddEditModal: FC<{ date: dayjs.Dayjs; @@ -277,7 +286,9 @@ export const AddEditModal: FC<{ if ( key.value.some( - (p) => p.content.length > (key.maximumCharacters || 1000000) + (p) => { + return countCharacters(p.content, key?.integration?.identifier || '') > (key.maximumCharacters || 1000000); + } ) ) { if ( @@ -385,16 +396,16 @@ export const AddEditModal: FC<{ instructions="You are an assistant that help the user to schedule their social media posts, everytime somebody write something, try to use a function call, if not prompt the user that the request is invalid and you are here to assists with social media posts" /> )} -
@@ -420,7 +431,7 @@ export const AddEditModal: FC<{ ) : (
-
- { + if (isUSCitizen()) { + return `${time === 12 ? 12 : time%12}:00 ${time >= 12 ? "PM" : "AM"}` + } else { + return `${time}:00` + } +} + export const days = [ 'Monday', 'Tuesday', @@ -91,7 +100,7 @@ export const DayView = () => { .startOf('day') .add(option[0].time, 'minute') .local() - .format('HH:mm')} + .format(isUSCitizen() ? "hh:mm A": "HH:mm")}
{ {hours.map((hour) => (
- {hour.toString().padStart(2, '0')}:00 + {/* {hour.toString().padStart(2, '0')}:00 */} + {convertTimeFormatBasedOnLocality(hour)}
{days.map((day, indexDay) => ( diff --git a/apps/frontend/src/components/launches/filters.tsx b/apps/frontend/src/components/launches/filters.tsx index e469153d..db21fa5b 100644 --- a/apps/frontend/src/components/launches/filters.tsx +++ b/apps/frontend/src/components/launches/filters.tsx @@ -3,6 +3,7 @@ import { useCalendar } from '@gitroom/frontend/components/launches/calendar.cont import clsx from 'clsx'; import dayjs from 'dayjs'; import { useCallback } from 'react'; +import { isUSCitizen } from './helpers/isuscitizen.utils'; export const Filters = () => { const week = useCalendar(); @@ -12,30 +13,30 @@ export const Filters = () => { .year(week.currentYear) .isoWeek(week.currentWeek) .day(week.currentDay) - .format('DD/MM/YYYY') + .format(isUSCitizen() ? 'MM/DD/YYYY' :'DD/MM/YYYY') : week.display === 'week' ? dayjs() .year(week.currentYear) .isoWeek(week.currentWeek) .startOf('isoWeek') - .format('DD/MM/YYYY') + + .format(isUSCitizen() ? 'MM/DD/YYYY' :'DD/MM/YYYY') + ' - ' + dayjs() .year(week.currentYear) .isoWeek(week.currentWeek) .endOf('isoWeek') - .format('DD/MM/YYYY') + .format(isUSCitizen() ? 'MM/DD/YYYY' :'DD/MM/YYYY') : dayjs() .year(week.currentYear) .month(week.currentMonth) .startOf('month') - .format('DD/MM/YYYY') + + .format(isUSCitizen() ? 'MM/DD/YYYY' :'DD/MM/YYYY') + ' - ' + dayjs() .year(week.currentYear) .month(week.currentMonth) .endOf('month') - .format('DD/MM/YYYY'); + .format(isUSCitizen() ? 'MM/DD/YYYY' :'DD/MM/YYYY'); const setDay = useCallback(() => { week.setFilters({ diff --git a/apps/frontend/src/components/launches/general.preview.component.tsx b/apps/frontend/src/components/launches/general.preview.component.tsx index a1abdaa2..e6eae31c 100644 --- a/apps/frontend/src/components/launches/general.preview.component.tsx +++ b/apps/frontend/src/components/launches/general.preview.component.tsx @@ -5,6 +5,7 @@ import clsx from 'clsx'; import { VideoOrImage } from '@gitroom/react/helpers/video.or.image'; import { Chakra_Petch } from 'next/font/google'; import { FC } from 'react'; +import { textSlicer } from '@gitroom/helpers/utils/count.length'; const chakra = Chakra_Petch({ weight: '400', subsets: ['latin'] }); export const GeneralPreviewComponent: FC<{maximumCharacters?: number}> = (props) => { @@ -14,7 +15,8 @@ export const GeneralPreviewComponent: FC<{maximumCharacters?: number}> = (props) removeMarkdown: true, saveBreaklines: true, specialFunc: (text: string) => { - return text.slice(0, props.maximumCharacters || 10000) + '' + text?.slice(props.maximumCharacters || 10000) + ''; + const {start, end} = textSlicer(integration?.identifier || '', props.maximumCharacters || 10000, text); + return text.slice(start, end) + '' + text?.slice(end) + ''; }, }); diff --git a/apps/frontend/src/components/launches/helpers/date.picker.tsx b/apps/frontend/src/components/launches/helpers/date.picker.tsx index 1e1b42c7..38bed701 100644 --- a/apps/frontend/src/components/launches/helpers/date.picker.tsx +++ b/apps/frontend/src/components/launches/helpers/date.picker.tsx @@ -3,6 +3,7 @@ import dayjs from 'dayjs'; import { Calendar, TimeInput } from '@mantine/dates'; import { useClickOutside } from '@mantine/hooks'; import { Button } from '@gitroom/react/form/button'; +import { isUSCitizen } from './isuscitizen.utils'; export const DatePicker: FC<{ date: dayjs.Dayjs; @@ -39,7 +40,7 @@ export const DatePicker: FC<{ onClick={changeShow} ref={ref} > -
{date.format('DD/MM/YYYY HH:mm')}
+
{date.format(isUSCitizen() ? 'MM/DD/YYYY hh:mm A' : 'DD/MM/YYYY HH:mm')}
{ + const userLanguage = navigator.language || navigator.languages[0]; + return userLanguage.startsWith('en-US') +} \ No newline at end of file diff --git a/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx b/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx index a0859429..e6fe34b2 100644 --- a/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx +++ b/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx @@ -17,7 +17,7 @@ const YoutubeSettings: FC = () => { const { register, control } = useSettings(); return (
- +