mirror of
https://github.com/fergalmoran/radio-otherway.git
synced 2025-12-22 09:50:29 +00:00
Fix build
This commit is contained in:
3
web/.env
3
web/.env
@@ -7,8 +7,9 @@ GOOGLE_APPLICATION_CREDENTIALS=serviceAccount.json
|
||||
|
||||
#calendar api
|
||||
GOOGLE_CALENDAR_PROJECT_ID=47147490249
|
||||
GOOGLE_CALENDAR_ID=geh501qel59lf3505v2huebo18@group.calendar.google.com
|
||||
LIVE_GOOGLE_CALENDAR_ID=geh501qel59lf3505v2huebo18@group.calendar.google.com
|
||||
GOOGLE_CALENDAR_ID=7732f7973f574db2638371394769a94aad5e38b98362d528cd985728d98cf3bd@group.calendar.google.com
|
||||
DEBUG_GOOGLE_CALENDAR_ID=7732f7973f574db2638371394769a94aad5e38b98362d528cd985728d98cf3bd@group.calendar.google.com
|
||||
|
||||
GOOGLE_CALENDAR_API_KEY=AIzaSyAMvrSrwqvz9o4Y8b-0zneU-REWDIzuKR0
|
||||
GOOGLE_CALENDAR_CREDENTIALS_CLIENT_EMAIL="otherway-calendar-proxy@radio-otherway.iam.gserviceaccount.com"
|
||||
|
||||
2
web/.idea/modules.xml
generated
2
web/.idea/modules.xml
generated
@@ -2,7 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/web.iml" filepath="$PROJECT_DIR$/.idea/web.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/radio-otherway-web.iml" filepath="$PROJECT_DIR$/.idea/radio-otherway-web.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
5
web/.vscode/settings.json
vendored
5
web/.vscode/settings.json
vendored
@@ -13,5 +13,8 @@
|
||||
".yarn": true
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"editor.fontFamily": "Cascadia Code",
|
||||
"editor.fontWeight": "350",
|
||||
"editor.tabSize": 2
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"dev": "node ./server.js",
|
||||
"debug": "node ./server.js",
|
||||
"dev-nossl": "next dev",
|
||||
"build": "next build && next export",
|
||||
"build-export": "next build && next export",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import PrivacyComponent from "@/components/boilerplate/PrivacyComponent";
|
||||
import { PrivacyComponent } from "@/components/boilerplate";
|
||||
|
||||
const PrivacyPage = () => {
|
||||
return <PrivacyComponent/>
|
||||
}
|
||||
return <PrivacyComponent />;
|
||||
};
|
||||
|
||||
export default PrivacyPage;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import TosComponent from "@/components/boilerplate/TosComponent";
|
||||
import { TosComponent } from "@/components/boilerplate";
|
||||
|
||||
const TosPage = () => {
|
||||
return <TosComponent />;
|
||||
|
||||
4
web/src/components/boilerplate/index.ts
Normal file
4
web/src/components/boilerplate/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import PrivacyComponent from "./PrivacyComponent";
|
||||
import TosComponent from "./TosComponent";
|
||||
|
||||
export { PrivacyComponent, TosComponent };
|
||||
@@ -1,25 +1,26 @@
|
||||
"use client";
|
||||
import { Show } from "@/models";
|
||||
import React from "react";
|
||||
import React, { useContext } from "react";
|
||||
import { MdAddAlarm } from "react-icons/md";
|
||||
import { useAuth } from "reactfire";
|
||||
import { useAuth, useUser } from "reactfire";
|
||||
import ToastService from "./toast/toastService";
|
||||
import { AuthProfileContext } from "@/lib/auth/AuthProfileProvider";
|
||||
|
||||
const RemindMeButton = ({ showId }: { showId: string }) => {
|
||||
const { user } = useAuth();
|
||||
const { status, data: user } = useUser();
|
||||
const createShowReminder = async () => {
|
||||
if (user?.id) {
|
||||
if (user?.uid) {
|
||||
const response = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/api/reminders`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
userId: user?.id,
|
||||
showId: user?.id,
|
||||
}),
|
||||
userId: user?.uid,
|
||||
showId: user?.uid
|
||||
})
|
||||
}
|
||||
);
|
||||
if (response.status === 201) {
|
||||
|
||||
@@ -12,7 +12,7 @@ const ThemeSelector = () => {
|
||||
const elem = document.activeElement as HTMLElement;
|
||||
elem?.blur();
|
||||
setTheme(theme);
|
||||
}, []);
|
||||
}, [setTheme]);
|
||||
|
||||
return (
|
||||
<div title="Change Theme" className="dropdown-end dropdown">
|
||||
|
||||
@@ -31,7 +31,7 @@ const AuthProfileProvider: React.FC<React.PropsWithChildren> = ({ children }) =>
|
||||
logger.debug("AuthProfileProvider", "Error loading provider", err);
|
||||
});
|
||||
}
|
||||
}, [status, user]);
|
||||
}, [status, user, getUserProfile]);
|
||||
|
||||
const [profile, setProfile] = useState<Profile>();
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ const Users = {
|
||||
const data = userQuery.docs[0].data();
|
||||
return Profile.fromJson(data);
|
||||
}
|
||||
throw Error("Unable to find user");
|
||||
return undefined;
|
||||
},
|
||||
getNotifiable: async (): Promise<Profile[] | undefined> => {
|
||||
const usersQuery = await getDocs(
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
DocumentData,
|
||||
collection,
|
||||
CollectionReference,
|
||||
getFirestore
|
||||
getFirestore, initializeFirestore
|
||||
} from "firebase/firestore";
|
||||
|
||||
const firebaseConfig = {
|
||||
@@ -16,9 +16,7 @@ const firebaseConfig = {
|
||||
measurementId: process.env.NEXT_PUBLIC_MEASUREMENT_ID
|
||||
};
|
||||
const firebaseApp = initializeApp(firebaseConfig);
|
||||
const firestore = getFirestore(firebaseApp);
|
||||
|
||||
// initializeFirestore(firebaseApp, {}, "radio-otherway");
|
||||
const firestore = initializeFirestore(firebaseApp, { ignoreUndefinedProperties: true });
|
||||
const createCollection = <T = DocumentData>(collectionName: string) => {
|
||||
return collection(firestore, collectionName) as CollectionReference<T>;
|
||||
};
|
||||
|
||||
@@ -11,10 +11,13 @@ const getStartOfToday = (admin: any) => {
|
||||
return timestamp; // ex. 1631246400
|
||||
};
|
||||
const dateDifferenceInSeconds = (date1: Date, date2: Date) =>
|
||||
Math.abs((date1.getTime() - date2.getTime())) / 1000;
|
||||
Math.abs(date1.getTime() - date2.getTime()) / 1000;
|
||||
|
||||
const isDatePast = (firstDate: Date) =>
|
||||
firstDate.setHours(0, 0, 0, 0) <= new Date().setHours(0, 0, 0, 0);
|
||||
|
||||
const addSeconds = (date: Date, seconds: number) => {
|
||||
date.setSeconds(date.getSeconds() + seconds);
|
||||
return date;
|
||||
};
|
||||
export { getMonthName, getTime, getStartOfToday, dateDifferenceInSeconds, addSeconds };
|
||||
export { isDatePast, getMonthName, getTime, getStartOfToday, dateDifferenceInSeconds, addSeconds };
|
||||
|
||||
@@ -2,19 +2,12 @@ import calendar, { GOOGLE_CALENDAR_ID } from "@/lib/util/google/calendar";
|
||||
import logger from "../logging";
|
||||
|
||||
const getCalendarEntries = async (syncToken?: string) => {
|
||||
try {
|
||||
const e = await calendar.events.list({
|
||||
calendarId: GOOGLE_CALENDAR_ID,
|
||||
maxResults: 10,
|
||||
singleEvents: true,
|
||||
syncToken: syncToken
|
||||
});
|
||||
const events = _mapEvents(e);
|
||||
return events;
|
||||
} catch (err) {
|
||||
logger.error("calendarReader", "Unable to read events", err);
|
||||
}
|
||||
return null;
|
||||
return _mapEvents(e);
|
||||
};
|
||||
const _mapEvents = (events: any) => {
|
||||
const mapped = events.data.items.map((r: any) => ({
|
||||
|
||||
@@ -6,8 +6,12 @@ import { Settings, Shows } from "@/lib/db/collections";
|
||||
import { Show } from "@/models";
|
||||
import { callWebHook } from "@/lib/util/httpUtils";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
import { dateDifferenceInSeconds, isDatePast } from "@/lib/util/dateUtils";
|
||||
|
||||
type CalendarParseError = { code: number, errors: any[], stack: string, message: string }
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
let retry = false;
|
||||
do {
|
||||
try {
|
||||
logger.debug("Starting sync of shows from google calendar");
|
||||
const syncToken = await Settings.read("CalendarSyncToken");
|
||||
@@ -20,8 +24,10 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
} else {
|
||||
const entries: Show[] = e?.events.map((r: any) => Show.fromJson(r));
|
||||
for (const entry of entries) {
|
||||
if (entry.date !== "Invalid Date" && !isDatePast(new Date(entry.date))) {
|
||||
await Shows.set(entry.id, await Shows.wrapShow(entry));
|
||||
}
|
||||
}
|
||||
if (e?.syncToken) {
|
||||
await Settings.write("CalendarSyncToken", e?.syncToken);
|
||||
}
|
||||
@@ -36,11 +42,19 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
}
|
||||
res.status(StatusCodes.OK).json({ status: "OK", entries });
|
||||
}
|
||||
} catch (err) {
|
||||
} catch (err: CalendarParseError | any) {
|
||||
retry = false;
|
||||
if (err.code === 410) {
|
||||
if (!retry) { //only retry once
|
||||
await Settings.write("CalendarSyncToken", "");
|
||||
retry = true;
|
||||
}
|
||||
} else {
|
||||
logger.error(err);
|
||||
res.status(500).json({ status: "Error" });
|
||||
}
|
||||
|
||||
}
|
||||
} while (retry);
|
||||
res.end();
|
||||
};
|
||||
export default handler;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
import { reminders } from "@/lib/db";
|
||||
import { doc, setDoc } from "@firebase/firestore";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
|
||||
@@ -7,20 +6,21 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
if (req.method !== "POST") {
|
||||
res.status(StatusCodes.METHOD_NOT_ALLOWED);
|
||||
} else {
|
||||
const { userId, showId } = req.body;
|
||||
const docKey = `${userId}_${showId}`;
|
||||
const remindersRef = doc(reminders, docKey);
|
||||
await setDoc(
|
||||
remindersRef,
|
||||
{
|
||||
userId,
|
||||
showId,
|
||||
notifications: [
|
||||
{ secondsBefore: 60 * 60, destination: "353868065119" }, //just set a single reminder for an hour beforehand
|
||||
],
|
||||
},
|
||||
{ merge: true }
|
||||
);
|
||||
res.status(StatusCodes.NOT_IMPLEMENTED);
|
||||
// const { userId, showId } = req.body;
|
||||
// const docKey = `${userId}_${showId}`;
|
||||
// const remindersRef = doc(reminders, docKey);
|
||||
// await setDoc(
|
||||
// remindersRef,
|
||||
// {
|
||||
// userId,
|
||||
// showId,
|
||||
// notifications: [
|
||||
// { secondsBefore: 60 * 60, destination: "353868065119" }, //just set a single reminder for an hour beforehand
|
||||
// ],
|
||||
// },
|
||||
// { merge: true }
|
||||
// );
|
||||
}
|
||||
res.status(StatusCodes.CREATED);
|
||||
res.end();
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
import { doc, setDoc } from "@firebase/firestore";
|
||||
import logger from "@/lib/util/logging";
|
||||
import { Show } from "@/models";
|
||||
import { getCalendarEntries } from "@/lib/util/google/calendarReader";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
import { shows } from "@/lib/db/collections";
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const resourceId = req.headers["x-goog-resource-id"];
|
||||
const channelToken = req.headers["x-goog-channel-token"];
|
||||
const channelId = req.headers["x-goog-channel-id"];
|
||||
const resourceState = req.headers["x-goog-resource-state"];
|
||||
logger.debug(
|
||||
"Webhook callback",
|
||||
resourceId,
|
||||
channelToken,
|
||||
channelId,
|
||||
resourceState
|
||||
);
|
||||
|
||||
const changed = await getCalendarEntries();
|
||||
const entries = changed?.events.map((r: any) => Show.fromJson(r));
|
||||
for (const entry of entries) {
|
||||
const showRef = doc(shows, entry.id);
|
||||
await setDoc(
|
||||
showRef,
|
||||
{
|
||||
title: entry.title,
|
||||
date: entry.date,
|
||||
creator: entry.creator,
|
||||
},
|
||||
{ merge: true }
|
||||
);
|
||||
}
|
||||
res.status(StatusCodes.OK).json({ result: "We got pinged" });
|
||||
res.end();
|
||||
};
|
||||
export default handler;
|
||||
Reference in New Issue
Block a user