diff --git a/.env.example b/.env.example index da5ba53..df37186 100644 --- a/.env.example +++ b/.env.example @@ -13,3 +13,5 @@ S3_USE_SSL=false S3_ACCESS_KEY="localminio" S3_SECRET_KEY="localminio" S3_BUCKET="devbucket" + +FOCO_LIVE_AIRTABLE_APIKEY= diff --git a/package.json b/package.json index 952c39b..0dfaac3 100644 --- a/package.json +++ b/package.json @@ -30,11 +30,13 @@ "@nestjs/schedule": "^4.0.0", "@nestjs/swagger": "^7.1.11", "@willsoto/nestjs-prometheus": "^6.0.0", + "airtable": "^0.12.2", "axios": "^1.5.0", "bcrypt": "^5.1.1", "bull": "^4.11.5", "cache-manager": "^5.3.1", "cache-manager-redis-yet": "^4.1.2", + "fp-ts": "^2.16.3", "hbs": "^4.2.0", "minio": "^7.1.3", "open-graph-scraper": "^6.3.0", diff --git a/src/app.module.ts b/src/app.module.ts index ce55841..91f6de1 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -21,6 +21,7 @@ import { RedisClientOptions } from 'redis'; import { redisStore } from 'cache-manager-redis-yet'; import { RedirectsModule } from './redirects/redirects.module'; import { FileModule } from './file/file.module'; +import { FocoLiveModule } from './foco-live/foco-live.module'; @Module({ imports: [ @@ -76,6 +77,7 @@ import { FileModule } from './file/file.module'; KvModule, RedirectsModule, FileModule, + FocoLiveModule, ], controllers: [AppController], providers: [AppService], diff --git a/src/config/configuration.ts b/src/config/configuration.ts index 180f0ae..5a5d24c 100644 --- a/src/config/configuration.ts +++ b/src/config/configuration.ts @@ -28,5 +28,10 @@ export default () => ({ bucketName: process.env.FILE_BUCKET_NAME ?? process.env.S3_BUCKET ?? 'api.us.dev-files', // default file ttl in seconds defaultTtl: parseInt(process.env.FILE_DEFAULT_TTL ?? (30 * 24 * 60 * 60).toString()), + }, + focoLive: { + airtable: { + apiKey: process.env.FOCO_LIVE_AIRTABLE_APIKEY ?? '', + } } }); diff --git a/src/foco-live/foco-live.controller.ts b/src/foco-live/foco-live.controller.ts new file mode 100644 index 0000000..85ddc52 --- /dev/null +++ b/src/foco-live/foco-live.controller.ts @@ -0,0 +1,16 @@ +import { Controller, Get } from '@nestjs/common'; +import { FocoLiveService } from './foco-live.service'; +import { ApiTags } from '@nestjs/swagger'; + +@ApiTags('foco-live') +@Controller('foco-live') +export class FocoLiveController { + constructor( + private readonly focoLiveService: FocoLiveService, + ) { } + + @Get('events') + async getEvents() { + return this.focoLiveService.getEvents(); + } +} diff --git a/src/foco-live/foco-live.module.ts b/src/foco-live/foco-live.module.ts new file mode 100644 index 0000000..b5344a4 --- /dev/null +++ b/src/foco-live/foco-live.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { FocoLiveController } from './foco-live.controller'; +import { FocoLiveService } from './foco-live.service'; + +@Module({ + controllers: [FocoLiveController], + providers: [FocoLiveService] +}) +export class FocoLiveModule {} diff --git a/src/foco-live/foco-live.service.ts b/src/foco-live/foco-live.service.ts new file mode 100644 index 0000000..a31128f --- /dev/null +++ b/src/foco-live/foco-live.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import * as Airtable from 'airtable'; +import { AirtableBase } from 'airtable/lib/airtable_base'; + +const tables = { + venues: 'tblRi4wDorKqNJJbs', + events: 'tbl4RZ75QF5WefE7L', +} + +const compareDates = (a: any, b: any) => new Date(a.Date).getTime() - new Date(b.Date).getTime(); + +@Injectable() +export class FocoLiveService { + private readonly airtableBase: AirtableBase; + + constructor( + private readonly config: ConfigService, + ) { + this.airtableBase = new Airtable({ + apiKey: config.get('focoLive.airtable.apiKey'), + }).base('app1SjPrn5qrhr59J'); + } + + async getEvents() { + return (await this.airtableBase('Events').select({ + view: "Grid view", + }).all()) + .map(record => record.fields) + .sort(compareDates) + .reverse(); + } +} diff --git a/src/redirects/redirects.module.ts b/src/redirects/redirects.module.ts index e651331..b9bfc7c 100644 --- a/src/redirects/redirects.module.ts +++ b/src/redirects/redirects.module.ts @@ -1,7 +1,8 @@ import { Module } from '@nestjs/common'; import { RedirectsController } from './redirects.controller'; +import { RequiredReadingController } from './required-reading.controller'; @Module({ - controllers: [RedirectsController] + controllers: [RedirectsController, RequiredReadingController] }) -export class RedirectsModule {} +export class RedirectsModule { } diff --git a/yarn.lock b/yarn.lock index a068deb..7cfee5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1193,6 +1193,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.9.tgz#a70ec9d8fa0180a314c3ede0e20ea56ff71aed9a" integrity sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ== +"@types/node@>=8.0.0 <15": + version "14.18.63" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.63.tgz#1788fa8da838dbb5f9ea994b834278205db6ca2b" + integrity sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -1514,6 +1519,18 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abortcontroller-polyfill@^1.4.0: + version "1.7.5" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" + integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== + accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -1549,6 +1566,17 @@ agent-base@6: dependencies: debug "4" +airtable@^0.12.2: + version "0.12.2" + resolved "https://registry.yarnpkg.com/airtable/-/airtable-0.12.2.tgz#e53e66db86744f9bc684faa58881d6c9c12f0e6f" + integrity sha512-HS3VytUBTKj8A0vPl7DDr5p/w3IOGv6RXL0fv7eczOWAtj9Xe8ri4TAiZRXoOyo+Z/COADCj+oARFenbxhmkIg== + dependencies: + "@types/node" ">=8.0.0 <15" + abort-controller "^3.0.0" + abortcontroller-polyfill "^1.4.0" + lodash "^4.17.21" + node-fetch "^2.6.7" + ajv-formats@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -2743,6 +2771,11 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + events@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" @@ -3040,6 +3073,11 @@ forwarded@0.2.0: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== +fp-ts@^2.16.3: + version "2.16.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.16.3.tgz#0862d583cd8673717dbad8576c0f58afda27c83a" + integrity sha512-REm0sOecd4inACbAiFeOxpyOgB+f0OqhmZBBVOc5Ku1HqdroDU5uxYu9mybKj+be4DQ5L2YI6LuosjAfmuJCBQ== + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"