Skip to content

Commit

Permalink
Merge pull request #69 from TurunWappuradio/feat/showlist-archiver
Browse files Browse the repository at this point in the history
Feat/showlist archiver
  • Loading branch information
niemisami authored Jan 22, 2024
2 parents 6351819 + 31ec97d commit 249c17e
Show file tree
Hide file tree
Showing 20 changed files with 312 additions and 105 deletions.
1 change: 1 addition & 0 deletions .github/workflows/develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ jobs:
GA_CLIENT_X509_CERT_URL: ${{ secrets.GA_CLIENT_X509_CERT_URL}}
GA_SPREADSHEET_SHOWLIST: ${{ secrets.GA_SPREADSHEET_SHOWLIST}}
GA_SPREADSHEET_RANGE: ${{ secrets.GA_SPREADSHEET_RANGE}}
ARCHIVE_SOURCE_URL: ${{ secrets.ARCHIVE_SOURCE_URL}}
run: npm run build

- name: Configure AWS credentials
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ jobs:
GA_CLIENT_X509_CERT_URL: ${{ secrets.GA_CLIENT_X509_CERT_URL}}
GA_SPREADSHEET_SHOWLIST: ${{ secrets.GA_SPREADSHEET_SHOWLIST}}
GA_SPREADSHEET_RANGE: ${{ secrets.GA_SPREADSHEET_RANGE}}
ARCHIVE_SOURCE_URL: ${{ secrets.ARCHIVE_SOURCE_URL}}
run: npm run build

- name: Configure AWS credentials
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/verify-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,5 @@ jobs:
GA_CLIENT_X509_CERT_URL: ${{ secrets.GA_CLIENT_X509_CERT_URL}}
GA_SPREADSHEET_SHOWLIST: ${{ secrets.GA_SPREADSHEET_SHOWLIST}}
GA_SPREADSHEET_RANGE: ${{ secrets.GA_SPREADSHEET_RANGE}}
ARCHIVE_SOURCE_URL: ${{ secrets.ARCHIVE_SOURCE_URL}}
run: npm run build
33 changes: 33 additions & 0 deletions archiver/archive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Show, showsToGroups } from 'contentful/client';
import { Showlist } from 'google/client';

const showlistBaseUrl = process.env.ARCHIVE_SOURCE_URL;
const emptyResponse = { showsByDate: [], weekKeys: {} } as const;

/**
* Archive S3 bucket API
*/
export const fetchArchivedShowlist = async (showlistId: string) => {
if (!showlistBaseUrl) {
console.error('Arkiston polkua ei ole määritetty');
return emptyResponse;
}
const url = `${showlistBaseUrl}${showlistId}/showlist.json`;

try {
const response = await fetch(url);
const showlist: Show[] | Showlist = await response.json();

if (Array.isArray(showlist)) {
return showsToGroups(showlist);
}
if (showlist?.showsByDate) {
return showlist;
}
return emptyResponse;
} catch (error) {
console.error(error);
console.error('Ohjelmakartan nouto epäonnistui');
}
return emptyResponse;
};
135 changes: 135 additions & 0 deletions archiver/archiveCrawlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import {
Show,
fetchContent as fetchContentfulContent,
parseQueryResultToShowlist,
} from 'contentful/client';
import {
ShowlistDocument,
ShowlistQuery,
} from 'contentful/graphql/showlist.graphql';
import { parseSheetToShowList, showsToGroups } from 'google/client';
import { GoogleConfigSheets, getSheet } from 'google/google';
import { mkdirSync } from 'node:fs';
import fs from 'node:fs/promises';
import path from 'node:path';
import { getImagePath } from 'utils/fileHelpers';

export const archiveOldShowlists = async () => {
// NOTE: Uncomment for archiving contentful data
// const contentfullIds = [
// { showlistId: 'syssyradio2020', name: '2020-syssy' },
// { showlistId: 'wappuradio2021', name: '2021-wappu' },
// { showlistId: 'wappuradio2022', name: '2022-wappu' },
// { showlistId: 'syssyradio-2022', name: '2022-syssy' },
// ];
// for (const { showlistId, name } of contentfullIds) {
// await archiveContentful(showlistId, name);
// }
// NOTE: Uncomment for archiving google sheet data
// const sheetConfigs = [
// { name: '2023-wappu', showStartTime: '2023-04-20T12:00:00', config: { apiKey: process.env.GA_API_KEY, spreadsheetId: '1eHDK-MYm6B3BH8rewQr04-pd2IK4iFwsPY5HKkrVNJg', range: 'Ohjelmakartta!A3:J5' } },
// { name: '2023-syssy', showStartTime: '2023-04-20T12:00:00', config: { apiKey: process.env.GA_API_KEY, spreadsheetId: '18UqWSStevUGa_rdIi9zF6NuCzbZc7H1ZnVMaIObV_Cg', range: 'Ohjelmakartta!A3:J32' } }
// ];
// for(const { config, name, showStartTime } of sheetConfigs) {
// await archiveGogleSheet(config, name, showStartTime);
// }
};

/** Helpers */

const getArchivePath = (showlistDir: string) =>
path.join('.', 'stuff', 'archives', showlistDir);

const mkdirp = async (filePath: string) => {
try {
// Ensure dirs exists with mkdir
mkdirSync(filePath, { recursive: true });
} catch (error) {
// noop. Throws error if dirs exists
}
};

const archiveJson = async (archivePath: string, showlistData: {}) => {
const archiveFilePath = path.join(archivePath, `showlist.json`);
await fs.writeFile(archiveFilePath, JSON.stringify(showlistData), 'utf-8');
};

const downloadFile = async (url: string, destinationPath: string) => {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);

await fs.writeFile(destinationPath, buffer);
};

/** Contentful - Pre wappu 2023 */
const ARCHIVE_SOURCE_URL = process.env.ARCHIVE_SOURCE_URL || '';

const archiveContentful = async (showlistId: string, name: string) => {
const archivePath = getArchivePath(name);
const pictureFolder = path.join(archivePath, 'pictures');
mkdirp(archivePath);
mkdirp(pictureFolder);

const showlistResponse = await fetchContentfulContent<ShowlistQuery>(
ShowlistDocument,
{ showlistId }
);
// NOTE: when data is stored locally
// const showlistResponse = raw as ShowlistQuery;
const shows = parseQueryResultToShowlist(showlistResponse);

const showsWithNewFilePaths = await reconnectShowsWithLocalFiles(
shows,
pictureFolder,
ARCHIVE_SOURCE_URL
);
const showlistData = showsToGroups(showsWithNewFilePaths);

await archiveJson(archivePath, showlistData);
};

const reconnectShowsWithLocalFiles = async (
shows: Show[],
archivePath: string,
archiveUrl: string
): Promise<Show[]> => {
const showsWithLocalFiles = [];
for (const show of shows) {
const { name, pictureUrl } = show;
if (!pictureUrl) {
showsWithLocalFiles.push(show);
continue;
}
const extension = path.parse(pictureUrl).ext;
const newFilename = getImagePath('', name, extension);
const filePath = path.join(archivePath, newFilename);
const archiveFileUrl = path.join(archiveUrl, newFilename);
await downloadFile(pictureUrl, filePath);

showsWithLocalFiles.push({ ...show, pictureUrl: archiveFileUrl });
}
return showsWithLocalFiles;
};

/** Google Sheets - Post wappu 2023 */

const archiveGogleSheet = async (
config: GoogleConfigSheets,
name: string,
showStartTime: string
) => {
const archivePath = getArchivePath(name);
const pictureFolder = path.join(archivePath, 'pictures');
mkdirp(archivePath);
mkdirp(pictureFolder);

const showlistResponse = await getSheet(config);
const showlist = await parseSheetToShowList(showlistResponse, {
apiKey: process.env.GA_API_KEY,
fileUrlBase: path.join(ARCHIVE_SOURCE_URL, name, 'pictures'),
localFilePath: pictureFolder,
showStartTime,
});
await archiveJson(archivePath, showlist);
};
7 changes: 4 additions & 3 deletions components/ShoutBox/shoutbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ export const ChatWrapper = () => {

return (
<div
className={`w-full flex-col items-center ${shoutboxOpen ? 'flex' : 'hidden'
}`}
className={`w-full flex-col items-center ${
shoutboxOpen ? 'flex' : 'hidden'
}`}
>
<div className="flex w-full max-w-6xl items-end justify-end">
<button
Expand Down Expand Up @@ -157,7 +158,7 @@ const Chat = ({ limit, isOpen }: ShoutBoxProps) => {
color={index % 2 === 0 ? 'bg-blue' : 'bg-blue-light'}
isAdmin={isAdmin}
onBanClick={handleBanClick}
telegram={message.source === "telegram"}
telegram={message.source === 'telegram'}
/>
))}
{!wsConnected && (
Expand Down
12 changes: 10 additions & 2 deletions components/calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,11 @@ const Event: FC<{ event: Event }> = ({ event }) => {
const formatWithTime = (start: Date, end: Date) => {
const startFormatted = format(start, 'HH:mm', { locale: fi });
const endFormatted = format(end, 'HH:mm', { locale: fi });
return <>kello {startFormatted} &ndash; {endFormatted}</>;
return (
<>
kello {startFormatted} &ndash; {endFormatted}
</>
);
};

const formatWithoutTime = (start: Date, end: Date) => {
Expand All @@ -112,7 +116,11 @@ const formatWithoutTime = (start: Date, end: Date) => {

if (startFormatted === endFormatted) return 'Koko päivä';

return <>{startFormatted} &ndash; {endFormatted}</>;
return (
<>
{startFormatted} &ndash; {endFormatted}
</>
);
};

export default Calendar;
2 changes: 1 addition & 1 deletion components/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface MenuProps {
const Menu = ({ navigationItems, isOpen, closeMenu }: MenuProps) => (
<div
className={`
fixed top-0 left-0 z-30 h-screen w-full
fixed left-0 top-0 z-30 h-screen w-full
transform-gpu bg-blue-darkest
text-white transition-all md:hidden
${isOpen ? 'translate-x-0' : '-translate-x-full'}
Expand Down
4 changes: 2 additions & 2 deletions components/player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ const Player = ({ playing, onPlayPause, showsByDate }: PlayerProps) => {
setVideoOpen(!videoOpen);
};

const { picture, name, hosts } = show ?? {};
const url = name ? picture?.url ?? placeholderImage : testcard;
const { pictureUrl, name, hosts } = show ?? {};
const url = name ? pictureUrl ?? placeholderImage : testcard;
return (
<div className="flex justify-center p-6">
<div className="flex w-[21rem] max-w-[59rem] flex-wrap items-center rounded bg-blue-darkest md:w-full md:flex-nowrap md:justify-start">
Expand Down
6 changes: 4 additions & 2 deletions components/responsiveShowlist.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ const DateButton = ({ value, currentDate, onClick }: DateButton) => {
return (
<button
className={`w-full rounded-sm p-2 text-left capitalize text-white ${
(value === currentDate) ? 'bg-coral font-bold' : 'bg-blue-darkest hover:text-coral'
value === currentDate
? 'bg-coral font-bold'
: 'bg-blue-darkest hover:text-coral'
}`}
onClick={() => onClick(value)}
>
Expand Down Expand Up @@ -109,7 +111,7 @@ export const ResponsiveShowlist = ({

<div className="mr-auto w-full space-y-4 lg:ml-[10rem]">
{showsByDate[selectedDate]?.map((show, i) => (
<ShowCard show={show} key={show.date + i} index={i} />
<ShowCard show={show} key={show.start + i} index={i} />
))}
</div>
<div className="ml-4 hidden w-[10rem] shrink-0 flex-col space-y-2 lg:flex">
Expand Down
13 changes: 5 additions & 8 deletions components/showcard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import fi from 'date-fns/locale/fi';
import Image from 'next/image';
import { useState } from 'react';

import { contentfulImageLoader } from 'contentful/contentfulImageLoader';
import placeholderImage from '../public/kuva_puuttuu_v2.jpeg';
import { Show } from 'contentful/client';

Expand Down Expand Up @@ -31,7 +30,7 @@ export const ShowCard = ({ show, index, className, forceOpen }: ShowCard) => {
>
<Time start={show.start} end={show.end} />
<button
className={`group relative flex h-full w-full flex-col flex-col-reverse overflow-hidden rounded md:flex-row ${
className={`group relative flex h-full w-full flex-col-reverse overflow-hidden rounded md:flex-row ${
isExpanded
? 'flex rounded md:contents'
: 'bg-gradient-to-bl from-transparent via-transparent to-blue-darkest'
Expand Down Expand Up @@ -118,9 +117,8 @@ interface ShowImageProps {
}

const ShowImage = ({ show, isExpanded }: ShowImageProps) => {
const { picture } = show;
const url = picture?.url || placeholderImage;
const loader = picture?.url ? contentfulImageLoader : undefined;
const { pictureUrl, name } = show;
const url = pictureUrl || placeholderImage;

return (
<div
Expand All @@ -132,8 +130,7 @@ const ShowImage = ({ show, isExpanded }: ShowImageProps) => {
>
<Image
src={url}
loader={loader}
unoptimized={picture?.url ? false : true}
unoptimized
layout={'fill'}
objectFit="cover"
objectPosition={'65% 35%'}
Expand All @@ -142,7 +139,7 @@ const ShowImage = ({ show, isExpanded }: ShowImageProps) => {
? 'rounded-t md:rounded-b md:rounded-l md:rounded-l-none '
: 'opacity-70 transition duration-300 ease-in-out md:group-hover:scale-110 md:group-hover:opacity-100'
}`}
alt={picture?.title || ''}
alt={name || ''}
/>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion components/videoPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const VideoPlayer = () => {
</button>
</div>

<div className="h-96 py-6 px-[25px] md:h-[38rem]">
<div className="h-96 px-[25px] py-6 md:h-[38rem]">
<iframe
/** Add parent &parent=localhost if testing */
src="https://player.twitch.tv/?channel=turunwappuradio&parent=www.turunwappuradio.com&parent=turunwappuradio.com&muted=true"
Expand Down
Loading

0 comments on commit 249c17e

Please sign in to comment.