Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions apps/sync-alerts/src/services/parseAlertV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import type { Alert } from '@carrismetropolitana/api-types/gtfs-core';
/* * */

export default function parseAlertV2(item): Alert {
//
const parsedInformedEntity = item.alert.informed_entity.map((entity) => {

const alertData = item.alert ?? item;
const alertId = item.id ?? item.alert_id;
const parsedInformedEntity = alertData.informed_entity.map((entity) => {
if (entity.route_id) {
return {
line_id: entity.route_id.substring(0, 4),
Expand All @@ -24,8 +26,9 @@ export default function parseAlertV2(item): Alert {
});

return {
...item.alert,
alert_id: item.id,
...alertData,
alert_id: alertId,
coordinates: alertData.coordinates,
informed_entity: parsedInformedEntity,
};

Expand Down
38 changes: 23 additions & 15 deletions apps/sync-alerts/src/tasks/sync-alerts.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

/* * */

import parseAlertV2 from '@/services/parseAlertV2.js';
import { type BackofficeAlertSource } from '@/types/sources.js';
import { SERVERDB } from '@carrismetropolitana/api-services/SERVERDB';
import { SERVERDB_KEYS } from '@carrismetropolitana/api-settings';
import { type Alert } from '@carrismetropolitana/api-types/alerts';
import LOGGER from '@helperkits/logger';
import TIMETRACKER from '@helperkits/timer';
import { ServiceAlertResponse } from '@tmlmobilidade/types';
Expand All @@ -25,14 +22,22 @@ export const syncAlerts = async () => {

const backofficeTimer = new TIMETRACKER();

const alertsFeedResponse = await fetchData<ServiceAlertResponse>('https://go.tmlmobilidade.pt/hub/api/v1/alerts/gtfs');
const alertsGtfsFeedResponse = await fetchData<ServiceAlertResponse>('https://go.tmlmobilidade.pt/hub/api/v1/alerts/gtfs');

if (alertsGtfsFeedResponse.error || !alertsGtfsFeedResponse.data) {
LOGGER.error(`Failed to fetch Alerts GTFS feed from the backoffice: ${alertsGtfsFeedResponse.error}`);
return;
}

const alertsJsonFeedResponse = await fetchData<BackofficeAlertSource[]>('https://go.tmlmobilidade.pt/hub/api/v1/alerts');

if (alertsFeedResponse.error) {
LOGGER.error(`Failed to fetch Alerts feed from the backoffice: ${alertsFeedResponse.error}`);
if (alertsJsonFeedResponse.error || !alertsJsonFeedResponse.data) {
LOGGER.error(`Failed to fetch Alerts JSON feed from the backoffice: ${alertsJsonFeedResponse.error}`);
return;
}

const alertsFeedData: any = alertsFeedResponse.data;
const alertsGtfsFeedData = alertsGtfsFeedResponse.data;
const alertsJsonFeedData = alertsJsonFeedResponse.data;

LOGGER.info(`Fetched Alerts feed from the backoffice (${backofficeTimer.get()})`);

Expand All @@ -42,7 +47,7 @@ export const syncAlerts = async () => {

const protobufTimer = new TIMETRACKER();

await SERVERDB.set(SERVERDB_KEYS.NETWORK.ALERTS.PROTOBUF, JSON.stringify(alertsFeedData));
await SERVERDB.set(SERVERDB_KEYS.NETWORK.ALERTS.PROTOBUF, JSON.stringify(alertsGtfsFeedData));

LOGGER.info(`Saved Protobuf Alerts to ServerDB (${protobufTimer.get()})`);

Expand All @@ -51,7 +56,7 @@ export const syncAlerts = async () => {

const jsonTimer = new TIMETRACKER();

const allAlertsParsedV2: Alert[] = alertsFeedData?.entity.map(item => parseAlertV2(item));
const allAlertsParsedV2 = alertsJsonFeedData;

await SERVERDB.set(SERVERDB_KEYS.NETWORK.ALERTS.ALL, JSON.stringify(allAlertsParsedV2));

Expand All @@ -71,7 +76,7 @@ export const syncAlerts = async () => {
let sentNotificationCounter = 0;

for (const alertItem of allAlertsParsedV2) {
if (!allSentNotificationsSet.has(alertItem['_id'])) {
if (!allSentNotificationsSet.has(alertItem.alert_id)) {
try {
for (const entity of alertItem['informed_entity']) {
// Setup notification message
Expand All @@ -94,7 +99,7 @@ export const syncAlerts = async () => {
topic: '',
};
// Include alert id
notificationMessage.data.alertId = alertItem['_id'];
notificationMessage.data.alertId = alertItem.alert_id;
// Include title
if (alertItem.header_text?.translation?.length > 0) {
notificationMessage.notification.title = alertItem.header_text?.translation[0]?.text ?? '';
Expand All @@ -112,6 +117,9 @@ export const syncAlerts = async () => {
if (entity.route_id) {
notificationMessage.topic = `cm.realtime.alerts.line.${entity.route_id}`;
}
else if (entity.line_id) {
notificationMessage.topic = `cm.realtime.alerts.line.${entity.line_id}`;
}
else if (entity.stop_id) {
notificationMessage.topic = `cm.realtime.alerts.stop.${entity.stop_id}`;
}
Expand All @@ -126,11 +134,11 @@ export const syncAlerts = async () => {
// await firebaseAdmin.messaging().send(notificationMessage);
sentNotificationCounter++;
}
allSentNotificationsSet.add(alertItem['_id']);
LOGGER.success(`Sent notification for alert: ${alertItem['_id']}`);
allSentNotificationsSet.add(alertItem.alert_id);
LOGGER.success(`Sent notification for alert: ${alertItem.alert_id}`);
}
catch (error) {
LOGGER.error(`Failed to send notification for alert: ${alertItem['_id']}`);
LOGGER.error(`Failed to send notification for alert: ${alertItem.alert_id}`);
LOGGER.error(error);
continue;
}
Expand Down
12 changes: 12 additions & 0 deletions apps/sync-alerts/src/types/sources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* * */

import { type Alert } from '@carrismetropolitana/api-types/alerts';

/* * */

export type AlertInformedEntitySource = Alert['informed_entity'][number] & { line_id?: string };

export type BackofficeAlertSource = Omit<Alert, 'id' | 'informed_entity'> & {
alert_id: string
informed_entity: AlertInformedEntitySource[]
};
22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
"scripts": {
"build": "turbo run build",
"build:packages": "turbo run build --filter=./packages/*",
"dev": "dotenv-run -f ./environments/development/secrets/.env -- turbo run dev --concurrency=99",
"dev:server": "dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-server",
"dev:switch": "dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-switch",
"dev:sync-alert-metrics": "dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-alert-metrics",
"dev:sync-alerts": "dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-alerts",
"dev:sync-facilities": "dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-facilities",
"dev:sync-gtfs": "dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-gtfs",
"dev:sync-locations": "dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-locations",
"dev:sync-metrics": "dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-metrics",
"dev:sync-stores": "dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-stores",
"dev:sync-vehicles": "dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-vehicles",
"dev": "NODE_ENV=development dotenv-run -f ./environments/development/secrets/.env -- turbo run dev --concurrency=99",
"dev:server": "NODE_ENV=development dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-server",
"dev:switch": "NODE_ENV=development dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-switch",
"dev:sync-alert-metrics": "NODE_ENV=development dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-alert-metrics",
"dev:sync-alerts": "NODE_ENV=development dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-alerts",
"dev:sync-facilities": "NODE_ENV=development dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-facilities",
"dev:sync-gtfs": "NODE_ENV=development dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-gtfs",
"dev:sync-locations": "NODE_ENV=development dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-locations",
"dev:sync-metrics": "NODE_ENV=development dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-metrics",
"dev:sync-stores": "NODE_ENV=development dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-stores",
"dev:sync-vehicles": "NODE_ENV=development dotenv-run -f ./environments/development/secrets/.env -- turbo dev --filter=@carrismetropolitana/api-sync-vehicles",
"lint": "turbo run lint",
"rinse": "npx --yes @tmlmobilidade/repo-rinse"
},
Expand Down
2 changes: 2 additions & 0 deletions packages/types/src/api/alerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ interface LocalizedImage {
/**
* An Alert is the JSON equivalent of a GTFS-RT Service Alert message.
* Please use a SimplifiedAlert as many convenience operations are already correctly applied.
* Coordinates are optional and may not be present in all alerts. They are provided as a [latitude, longitude] pair.
*/
export interface Alert {
active_period: TimeRange[]
cause: Cause
coordinates?: [number, number]
description_text: TranslatedString
effect: Effect
header_text: TranslatedString
Expand Down
Loading