Skip to content

Commit

Permalink
v0.6.0: Added Pairi Daiza and Heidi Park, improved data points and fi…
Browse files Browse the repository at this point in the history
…xed Efteling

* Added tests to check if POI lists actually contain items

* Fixed Cedar Fair parks (except Kings Island)

* Fixed CDA image-less POIs and added CDA videos

* v0.5.2: Finally fixed Efteling, temp removed Beekse Bergen, fixed Kings Island, fixed Blijdorp

* v0.5.3: Changed from hard-coded Halloween to Events, improved ID's for some parks

* v0.5.4: Fixed Blijdorp and Beekse Bergen, sort of Universal fix

* v0.5.5: Finished Event implementation, added Toverland halloween event

* v0.5.6: Added Heidi Park, added event slugs

* v0.5.7: Fixed Blijdorp, added park searching, fixed broken tests

* v0.5.8: Added Pairi Daiza and Animal Facts

* v0.5.10: Implemented more tests, improved Pairi Daiza, added Efteling menus

* v0.6.0: Greatly improved Beekse Bergen, added a property to `supports` to indicate text type (markdown, text, ...)
  • Loading branch information
timyboy12345 authored Jan 26, 2025
1 parent a7237ee commit 8f73b1e
Show file tree
Hide file tree
Showing 173 changed files with 31,176 additions and 561 deletions.
19 changes: 0 additions & 19 deletions .github/workflows/qodana_code_quality.yml

This file was deleted.

10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ In the table below you will find the parks that are currently supported and the
| 🇧🇪 Bellewaerde | 🎡 | True | True | True | True | False |
| 🇧🇪 Bobbejaanland | 🎡 | True | True | False | True | False |
| 🇧🇪 Plopsalande de Panne | 🎡 | True | True | True | True | False |
| 🇧🇪 Pairi Daiza | 🦁 | False | True | True | True | False |
| 🇨🇦 La Ronde, Montreal | 🎡 | True | True | True | True | False |
| 🇩🇪 Phantasialand | 🎡 | True | True | True | True | False |
| 🇩🇪 Holiday Park | 🎡 | True | True | True | True | False |
| 🇩🇪 LegoLand Deutschland | 🎡 | False | False | False | False | False |
| 🇩🇪 LegoLand Deutschland | 🎡 | True | True | True | True | False |
| 🇩🇪 Hansa Park | 🎡 | True | True | True | True | False |
| 🇩🇪 Movie Park Germany | 🎡 | True | True | True | True | True |
| 🇩🇪 Heidi Park | 🎡 | True | True | True | True | False |
| 🇩🇰 Tivoli | 🎡 | True | True | True | False | False |
| 🇪🇸 Portaventura | 🎡 | True | True | True | True | False |
| 🇪🇸 Ferrari Land | 🎡 | True | True | True | True | False |
Expand All @@ -42,15 +44,15 @@ In the table below you will find the parks that are currently supported and the
| 🇮🇹 Mirabilandia | 🎡 | True | True | False | True | False |
| 🇳🇱 Efteling | 🎡 | True | True | True | True | False |
| 🇳🇱 Toverland | 🎡 | True | True | True | False | True |
| 🇳🇱 Walibi Holland | 🎡 | True | True | False | True | False |
| 🇳🇱 Walibi Holland | 🎡 | True | True | True | True | True |
| 🇳🇱 DippieDoe | 🎡 | True | False | False | False | False |
| 🇳🇱 Hellendoorn | 🎡 | True | True | True | True | False |
| 🇳🇱 Ouwehands Dierenpark | 🦁 | False | False | False | False | False |
| 🇳🇱 Wildlands | 🦁 | False | False | False | False | False |
| 🇳🇱 Blijdorp | 🦁 | False | False | True | False | False |
| 🇳🇱 Apenheul | 🦁 | False | False | False | False | False |
| 🇳🇱 Safaripark Beekse Bergen | 🦁 | False | True | False | False | False |
| 🇳🇱 Speelland Beekse Bergen | 🎡 | True | False | False | False | False |
| 🇳🇱 Safaripark Beekse Bergen | 🦁 | True | True | False | True | False |
| 🇳🇱 Speelland Beekse Bergen | 🎡 | True | True | False | True | False |
| 🇵🇱 Energylandia | 🎡 | True | False | True | False | False |
| 🇸🇪 Liseberg | 🎡 | True | True | False | True | False |
| 🇸🇪 Grona Lund | 🎡 | True | False | False | False | False |
Expand Down
10 changes: 8 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "themeparks-node-api",
"version": "0.5.1",
"version": "0.6.0",
"description": "An API which can retrieve theme park wait times.",
"author": "Tim Arendsen",
"private": false,
Expand Down Expand Up @@ -53,6 +53,7 @@
"reflect-metadata": "^0.2.2",
"rimraf": "^5.0.7",
"rxjs": "^7.8.1",
"sluggo": "^1.0.0",
"swagger-ui-express": "^5.0.1",
"typeorm": "^0.3.20",
"unzipper": "^0.12.1",
Expand Down
6 changes: 6 additions & 0 deletions src/_interfaces/event.category.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum EventCategory {
HALLOWEEN = 'HALLOWEEN',
WINTER = 'WINTER',
EASTER = 'EASTER',
OTHER = 'OTHER',
}
15 changes: 15 additions & 0 deletions src/_interfaces/park-event.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { EventCategory } from './event.category';
import { Poi } from './poi.interface';

export interface ThemeParkEvent {
fromDate?: string;
toDate?: string;
dates?: string[];
type: EventCategory;
slug: string;
name?: string;
subTitle?: string;
description?: string;
image?: string,
pois?: Poi[];
}
6 changes: 4 additions & 2 deletions src/_interfaces/park-supports.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ export interface ThemeParkSupports {
supportsTranslations: boolean;

/**
* @description Whether or not a park supports returning Halloween related items, such as scare zones and experiences
* @description Whether or not a park supports returning special event related items, such as Halloween scare zones and experiences or Christmas experiences
*/
supportsHalloween: boolean;
supportsEvents: boolean;

textType: "UNDEFINED" | "HTML" | "MARKDOWN";
}
2 changes: 2 additions & 0 deletions src/_interfaces/park.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ export enum Company {
SEAWORLD = 'SEAWORLD',
UNIVERSAL = 'UNIVERSAL',
PARQUES_REUNIDOS = 'PARQUES_REUNIDOS',
LIBEMA = 'LIBEMA',
MERLIN_ENTERTAINMENTS = 'MERLIN_ENTERTAINMENTS'
}
1 change: 1 addition & 0 deletions src/_interfaces/poi-categories.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export enum PoiCategory {
GUEST_SERVICES = 'GUEST_SERVICES',
PLAYGROUND = 'PLAYGROUND',
PARKING = 'PARKING',
ENTRANCE = 'ENTRANCE',
HALLOWEEN_WALKTROUGH = 'HALLOWEEN_WALKTROUGH',
HALLOWEEN_EVENT = 'HALLOWEEN_EVENT',
HALLOWEEN_HOUSE = 'HALLOWEEN_HOUSE',
Expand Down
11 changes: 11 additions & 0 deletions src/_interfaces/poi-fact.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ export interface PoiFact {
| 'capacity'
| 'inversion_count'
| 'passengers_per_car'
| 'animal_height'
| 'animal_width'
| 'animal_weight'
| 'animal_longevity'
| 'animal_diet'
| 'animal_class'
| 'animal_habitat'
| 'animal_iucn'
| 'animal_gestation'
| 'animal_offspring'
| 'animal_bigFive'
| string;
description?: string;
content?: string;
Expand Down
1 change: 1 addition & 0 deletions src/_interfaces/poi-video.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export interface PoiVideo {
platform: 'YOUTUBE' | 'VIMEO' | 'FACEBOOK' | 'URL' | 'OTHER',
embed_id?: string,
full_url?: string,
thumbnail?: string,
}
6 changes: 6 additions & 0 deletions src/_interfaces/poi.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Translation } from './translation.interface';
import { PoiMenuItemInterface } from './poi-menu-item.interface';
import { PoiFact } from './poi-fact.interface';
import { PoiVideo } from './poi-video.interface';
import { EventCategory } from './event.category';

export interface Poi {
/**
Expand All @@ -31,6 +32,11 @@ export interface Poi {
*/
original_category?: string;

/**
* The type of event this poi relates to, if available
*/
eventCategory?: EventCategory;

/**
* The name of the POI
*/
Expand Down
10 changes: 9 additions & 1 deletion src/_services/aio/aio-themepark.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class AioThemeparkService extends ThroughPoisThemeParkService {

private _tempToken: string;

// TODO: Some AIO parks offer localizations
constructor(protected readonly httpService: HttpService,
protected readonly configService: ConfigService,
private readonly transferService: AioTransferServiceService) {
Expand All @@ -44,7 +45,8 @@ export class AioThemeparkService extends ThroughPoisThemeParkService {
supportsRideWaitTimesHistory: false,
supportsPois: true,
supportsTranslations: false,
supportsHalloween: false,
textType: "UNDEFINED",
supportsEvents: false,
};
}

Expand Down Expand Up @@ -80,6 +82,8 @@ export class AioThemeparkService extends ThroughPoisThemeParkService {
'Content-Type': settings.contentType,
};

console.debug(" - AIO: Fetching Token");

const config: AxiosRequestConfig = { headers: headers };

return await this.httpService
Expand All @@ -90,6 +94,7 @@ export class AioThemeparkService extends ThroughPoisThemeParkService {
)
.toPromise()
.then(value => {
console.debug(` - AIO: API Key is ${value.data.token}`)
this._tempToken = value.data.token;
return this._tempToken;
})
Expand All @@ -110,6 +115,7 @@ export class AioThemeparkService extends ThroughPoisThemeParkService {
const headers = {
'Authorization': `Attractions-Io api-key="${this.getApiKey()}", installation-token="${token}"`,
'Date': settings.latestUpdate,
'Occasio-Data-Version': settings.latestUpdate,
'User-Agent': settings.userAgent,
};

Expand All @@ -121,6 +127,8 @@ export class AioThemeparkService extends ThroughPoisThemeParkService {
maxRedirects: 0,
};

console.debug(` - AIO: Fetching Data Package URL for ${settings.latestUpdate}`);

return new Promise((resolve, reject) => {
this.httpService
.get(
Expand Down
6 changes: 6 additions & 0 deletions src/_services/parks/parks.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ import { MirabilandiaService } from '../../parks/parques-reunidos/mirabilandia/m
import {
MarinelandCoteDazurService
} from '../../parks/parques-reunidos/marineland-cote-dazur/marineland-cote-dazur.service';
import { MerlinEntertainmentsService } from '../../parks/merlin-entertainments/merlin-entertainments.service';
import { PairiDaizaService } from '../../parks/pairi-daiza/pairi-daiza.service';

@Injectable()
export class ParksService {
Expand Down Expand Up @@ -120,6 +122,8 @@ export class ParksService {
private readonly _gardaland: GardalandService,
private readonly _mirabilandia: MirabilandiaService,
private readonly _marineLandCoteDazur: MarinelandCoteDazurService,
private readonly _merlinEntertainmentsService: MerlinEntertainmentsService,
private readonly _pairiDaizaService: PairiDaizaService,
) {
this._parks = [];
this._parks.push(_eftelingService);
Expand Down Expand Up @@ -168,12 +172,14 @@ export class ParksService {
this._parks.push(_gardaland)
this._parks.push(_mirabilandia)
this._parks.push(_marineLandCoteDazur)
this._parks.push(_pairiDaizaService)

this._companies = [];
this._companies.push(_sixflagsService);
this._companies.push(_cedarFairService);
this._companies.push(_seaworldCompanyService);
this._companies.push(_universalService);
this._companies.push(_merlinEntertainmentsService);
}

public async getParks(): Promise<ThemeParkService[]> {
Expand Down
5 changes: 5 additions & 0 deletions src/_services/themepark/theme-park.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ThemePark } from '../../_interfaces/park.interface';
import { Poi } from '../../_interfaces/poi.interface';
import { ThemeParkSupports } from '../../_interfaces/park-supports.interface';
import { ThemeParkOpeningTimes } from '../../_interfaces/park-openingtimes.interface';
import { ThemeParkEvent } from '../../_interfaces/park-event.interface';

@Injectable()
export class ThemeParkService {
Expand Down Expand Up @@ -93,4 +94,8 @@ export class ThemeParkService {
async getOpeningTimes(): Promise<ThemeParkOpeningTimes[]> {
throw new NotImplementedException("Could not get opening times");
}

async getEvents(): Promise<ThemeParkEvent[]> {
throw new NotImplementedException("Could not get events");
}
}
1 change: 1 addition & 0 deletions src/controllers/blog-posts/blog-posts.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export class BlogPostsController {
return this.blogPostService.getAll(this.localeService.getLocale());
}

// TODO: Should more information be cached?
@ApiOkResponse({
type: BlogPost,
isArray: true,
Expand Down
30 changes: 29 additions & 1 deletion src/controllers/park/park.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { LanguageInterceptor } from '../../_interceptors/language.interceptor';
import { ThemeParkOpeningTimes } from '../../_interfaces/park-openingtimes.interface';
import { ThemeParkOpeningHourDto } from '../../_dtos/theme-park-opening-hour.dto';
import { CACHE_MANAGER, CacheInterceptor } from '@nestjs/cache-manager';
import { ThemeParkEvent } from '../../_interfaces/park-event.interface';

@ApiTags('Themeparks')
@Controller('parks/:id')
Expand Down Expand Up @@ -265,7 +266,7 @@ export class ParkController {
async getParkHalloweenRelatedItems(@Param() params, @Query() query): Promise<Poi[]> {
const park = await this.parksService.findPark(params.id, true);

if (!park.getFullInfo().supports.supportsHalloween) {
if (!park.getFullInfo().supports.supportsEvents) {
throw new BadRequestException('This park does not support halloween related items');
}

Expand Down Expand Up @@ -306,4 +307,31 @@ export class ParkController {

return await park.getOpeningTimes();
}

@Get('events')
@UseInterceptors(CacheInterceptor, LanguageInterceptor)
@ApiParam({
name: 'id',
type: 'string',
description: 'The park id',
})
@ApiResponse({
status: 200,
description: 'All events of a specific park, with all available data',
isArray: true,
type: ThemeParkOpeningHourDto,
})
@ApiResponse({
status: 404,
description: 'The requested park could not be found',
})
async getParkEvents(@Param() params): Promise<ThemeParkEvent[]> {
const park = await this.parksService.findPark(params.id, true);

if (!park.getFullInfo().supports.supportsEvents) {
throw new BadRequestException('This park does not support events');
}

return await park.getEvents();
}
}
Loading

0 comments on commit 8f73b1e

Please sign in to comment.