From f7b0981b7d2a02a89dd3ca569f9921e8e52f0b8e Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Tue, 22 Nov 2022 12:12:12 +0800 Subject: [PATCH] Parse subscription filter in rules --- packages/rule-handler/package.json | 3 +- .../{sendNotification.ts => notification.ts} | 7 +- packages/rule-handler/src/rule.ts | 74 +++++++++++++++---- 3 files changed, 63 insertions(+), 21 deletions(-) rename packages/rule-handler/src/{sendNotification.ts => notification.ts} (94%) diff --git a/packages/rule-handler/package.json b/packages/rule-handler/package.json index 6c17ca61b..41f80a65e 100644 --- a/packages/rule-handler/package.json +++ b/packages/rule-handler/package.json @@ -25,6 +25,7 @@ "axios": "^0.27.2", "dotenv": "^16.0.1", "firebase-admin": "^10.0.2", - "jsonwebtoken": "^8.5.1" + "jsonwebtoken": "^8.5.1", + "search-query-parser": "^1.6.0" } } diff --git a/packages/rule-handler/src/sendNotification.ts b/packages/rule-handler/src/notification.ts similarity index 94% rename from packages/rule-handler/src/sendNotification.ts rename to packages/rule-handler/src/notification.ts index c7cad5abc..31bfc20ca 100644 --- a/packages/rule-handler/src/sendNotification.ts +++ b/packages/rule-handler/src/notification.ts @@ -56,9 +56,9 @@ export const getDeviceTokens = async ( } export const getBatchMessages = ( - title: string, messages: string[], tokens: string[], + title?: string, imageUrl?: string ): Message[] => { const batchMessages: Message[] = [] @@ -93,8 +93,5 @@ export const sendMulticastPushNotifications = async ( export const sendBatchPushNotifications = async ( messages: Message[] ): Promise => { - const res = await getMessaging().sendAll(messages) - console.debug('res', res) - - return res + return getMessaging().sendAll(messages) } diff --git a/packages/rule-handler/src/rule.ts b/packages/rule-handler/src/rule.ts index 2e57f1a88..990de516d 100644 --- a/packages/rule-handler/src/rule.ts +++ b/packages/rule-handler/src/rule.ts @@ -2,9 +2,10 @@ import { getBatchMessages, getDeviceTokens, sendBatchPushNotifications, -} from './sendNotification' +} from './notification' import { getAuthToken, PubSubData } from './index' import axios from 'axios' +import { parse, SearchParserKeyWordOffset } from 'search-query-parser' export enum RuleActionType { AddLabel = 'ADD_LABEL', @@ -30,6 +31,59 @@ export interface Rule { updatedAt: Date } +interface SearchFilter { + subscriptionFilter?: string +} + +const parseSearchFilter = (filter: string): SearchFilter => { + const searchFilter = filter ? filter.replace(/\W\s":/g, '') : undefined + const result: SearchFilter = {} + + if (!searchFilter || searchFilter === '*') { + return result + } + + const parsed = parse(searchFilter, { + keywords: ['subscription'], + tokenize: true, + }) + if (parsed.offsets) { + const keywords = parsed.offsets + .filter((offset) => 'keyword' in offset) + .map((offset) => offset as SearchParserKeyWordOffset) + + for (const keyword of keywords) { + switch (keyword.keyword) { + case 'subscription': + result.subscriptionFilter = keyword.value + } + } + } + + return result +} + +const isValidData = (filter: string, data: PubSubData): boolean => { + const searchFilter = parseSearchFilter(filter) + + if (searchFilter.subscriptionFilter) { + return isValidSubscription(searchFilter.subscriptionFilter, data) + } + + return true +} + +const isValidSubscription = ( + subscriptionFilter: string, + data: PubSubData +): boolean => { + if (!data.subscription) { + return false + } + + return subscriptionFilter === '*' || data.subscription === subscriptionFilter +} + export const getEnabledRules = async ( userId: string, apiEndpoint: string, @@ -77,9 +131,7 @@ export const triggerActions = async ( jwtSecret: string ) => { for (const rule of rules) { - // TODO: filter out rules that don't match the trigger - if (!data.subscription) { - console.debug('no subscription') + if (!isValidData(rule.filter, data)) { continue } @@ -94,14 +146,7 @@ export const triggerActions = async ( console.log('No notification messages provided') continue } - await sendNotification( - userId, - data.subscription, - action.params, - apiEndpoint, - jwtSecret, - data.image - ) + await sendNotification(userId, action.params, apiEndpoint, jwtSecret) } } } @@ -109,20 +154,19 @@ export const triggerActions = async ( export const sendNotification = async ( userId: string, - subscription: string, messages: string[], apiEndpoint: string, jwtSecret: string, + title?: string, image?: string ) => { - const title = `📫 - ${subscription} has published a new article` // get device tokens by calling api const tokens = await getDeviceTokens(userId, apiEndpoint, jwtSecret) const batchMessages = getBatchMessages( - title, messages, tokens.map((t) => t.token), + title, image )