Skip to content

Commit

Permalink
feat/always show groupchats (#274)
Browse files Browse the repository at this point in the history
* feat: allow groupchats to be shown to unauthenticated users

* fix: hide promoted field from normal user

* fix: https prefixing

* fix: lint

* fix: link for adding groupchats
  • Loading branch information
geisterfurz007 authored Jan 12, 2024
1 parent e5c9a0b commit d4655ec
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 17 deletions.
6 changes: 4 additions & 2 deletions packages/cms/src/access/require-one-of.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {type GeneratedTypes} from 'payload';
import {type Access} from 'payload/config';
import {type FieldAccess, type TypeWithID} from 'payload/types';
import {type SessionUser} from '../collections/users';

type Role = GeneratedTypes['collections']['users']['roles'][number];

export function requireOneOf(...args: Role[]): Access<unknown, SessionUser> {
export function requireOneOf(
...args: Role[]
): FieldAccess<unknown & TypeWithID, SessionUser> {
return ({req}) => {
const user: SessionUser = req.user;

Expand Down
22 changes: 21 additions & 1 deletion packages/cms/src/collections/groupchats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ export const Groupchats: CollectionConfig = {
{label: 'WhatsApp', value: 'whatsapp'},
],
},
{
name: 'showUnauthenticated',
type: 'checkbox',
label: 'Show to unauthenticated users?',
defaultValue: false,
admin: {
description:
'This potentially allows bots to scrape this groupchat from the page. If you have measures to prevent botting, you can select this for more visibility.',
// Facebook groups / Instagram profiles are always shown, so we just hide this checkbox in that case
condition: (data) =>
data.platform && !['facebook', 'instagram'].includes(data.platform),
},
},
{name: 'description', type: 'text'},
{
name: 'url',
Expand All @@ -92,6 +105,9 @@ export const Groupchats: CollectionConfig = {
],
},
validate: (url, {data}) => {
// Validate only server-side to allow beforeValidate to run properly before this.
if (typeof window !== 'undefined') return true;

if (!url) return 'This field is required.';

const urlMatcher = platformUrlMatchers[data.platform];
Expand All @@ -116,8 +132,10 @@ export const Groupchats: CollectionConfig = {
type: 'number',
min: 0,
max: 100,
required: true,
defaultValue: 0,
access: {
read: requireOneOf('groupchats-admin'),
},
admin: {
description:
'This value may be used to push results. A value of 0 means no promotion. Any value between 1 and 100 may be used to order promoted groupchats.',
Expand Down Expand Up @@ -208,6 +226,8 @@ export const Groupchats: CollectionConfig = {
const typesenseDoc = {
...sanitized,
id: doc.id.toString(),
promoted: doc.promoted ?? 0,
showUnauthenticated: doc.showUnauthenticated ?? false,
keywords: keywords.docs.map((k) => k.value),
};
await typesenseClient
Expand Down
7 changes: 6 additions & 1 deletion packages/cms/src/cron-jobs/groupchat-sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ const schema: CollectionCreateSchema = {
type: 'string',
facet: true,
},
{
name: 'showUnauthenticated',
type: 'bool',
},
{
name: 'promoted',
type: 'int32',
Expand Down Expand Up @@ -73,9 +77,10 @@ const syncGroupchatsToTypesense = async () => {
});

const typesenseChats = groupchats.map(
({id, createdAt, updatedAt, keywords, ...rest}) => ({
({id, createdAt, updatedAt, keywords, showUnauthenticated, ...rest}) => ({
...rest,
id: id.toString(),
showUnauthenticated: showUnauthenticated ?? false,
keywords:
keywords?.map((keyword) =>
typeof keyword === 'object' ? keyword.value : undefined,
Expand Down
6 changes: 4 additions & 2 deletions packages/cms/src/graphql/queries/groupchat-search-token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ export const groupchatSearchTokenQuery: QueryFactory<string, void> = (
resolve: async (_: unknown, __, context) => {
const {isLoggedIn} = await getAuthStateFromRequest(context.req);

const accessiblePlatforms: GroupchatPlatform[] = ['facebook'];
const accessiblePlatforms: GroupchatPlatform[] = ['facebook', 'instagram'];

if (isLoggedIn) {
accessiblePlatforms.push('discord', 'signal', 'telegram', 'whatsapp');
}

const filterBy = `platform:=[${accessiblePlatforms.join(',')}]`;
const filterBy = `platform:=[${accessiblePlatforms.join(
',',
)}] || showUnauthenticated: true`;

return typesenseClient
.keys()
Expand Down
1 change: 1 addition & 0 deletions packages/cms/src/payload-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface Groupchat {
description?: string | null;
url: string;
keywords?: (number | GroupchatKeyword)[] | null;
showUnauthenticated?: boolean | null;
promoted: number;
owners?: (string | User)[] | null;
updatedAt: string;
Expand Down
1 change: 1 addition & 0 deletions packages/scripts/src/scrape-groupchats/groupchat.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export type Groupchat = {
name: string;
url: string;
showUnauthenticated?: boolean;
};

export type ProcessedGroupchat = Groupchat & {platform: string};
1 change: 1 addition & 0 deletions packages/scripts/src/scrape-groupchats/sources/wixsite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const scrapeFromWix = async (url: string): Promise<Groupchat[]> => {
return {
url,
name: a.innerText,
showUnauthenticated: true,
};
});
};
14 changes: 3 additions & 11 deletions packages/web/src/app/groupchats/components/group-chat-search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,14 @@ export const GroupChatSearch: FC<{isLoggedIn: boolean}> = ({isLoggedIn}) => {
<p>Not seeing what you are looking for?</p>
<p>
<InformationCircleIcon className='mr-2 inline-block h-6 w-6 text-brand-800' />
Ask the group&apos;s admin to shoot me a message{' '}
<a
className='underline decoration-brand-500'
href='https://discord.com/users/290193372407136256'
target='_blank'
rel='noreferrer'
>
over on Discord
</a>{' '}
to get the group on here!
Ask the group&apos;s admin to head over{' '}
<a href={process.env.NEXT_PUBLIC_PAYLOAD_URL}>here</a>!
</p>

{!isLoggedIn && (
<p>
<ExclamationTriangleIcon className='mr-2 inline-block h-6 w-6 text-warning' />
Only Facebook groups and Instagram pages are available without{' '}
Only specific chats are available without{' '}
<Link
href='#'
onClick={() => navigateToLogin()}
Expand Down

0 comments on commit d4655ec

Please sign in to comment.