Options
All
  • Public
  • Public/Protected
  • All
Menu

cc-api [WIP]

TypeScript Build Status Maintainability Test Coverage

A bare-bones homebrew implementation of the Caribbean Cinemas API, being built in TypeScript using web scrapers. An official API exists, this is just a fun exercise. For personal use only.

Note: Since the data for this API is being obtained by scraping the web page, it is not expected to be accurate forever. In fact, new data will be unobtainable once the web page changes, at least until the scrapers get updated to compensate. In any case, this is a toy project and should be treated as such.

How To

Run the API

yarn serve

Scrape theatres and update database

yarn scrape-theatres

Scrape Now Showing Movies and update database

yarn tasks --now-showing

Scrape Coming Soon Movies and update database

yarn tasks --coming-soon

Add all movie runs for all theatres

yarn add-movie-runs

To-Do

  • General

    • Logging
    • Throttling
    • Versioning
    • JSONAPI Schema Serialization
    • Documentation
    • Test Controllers / Use fixtures
    • Caching
    • MongoDB Document Hydration / Task Scheduling
    • MongoDB Document Cleanup / Document Expiration
    • Idempotent tasks
    • Pagination
    • TravisCI Deployment
  • Specific

    • Refactor to improve code quality
    • Add more tests
    • Improve documentation

Index

Variables

Const API_GIT_URL

API_GIT_URL: "https://github.com/rnegron/cc-api" = "https://github.com/rnegron/cc-api"

Const API_URL

API_URL: "" = ""

Const ActorModel

ActorModel: IActorModel = mongoose.model<IActor, IActorModel>('Actor', ActorSchema)

Const ActorSchema

ActorSchema: Schema<any> = new mongoose.Schema({__v: { type: Number, select: false },name: { type: String },})

Const CC_URL

CC_URL: "https://caribbeancinemas.com" = "https://caribbeancinemas.com"

Const MovieModel

MovieModel: IMovieModel = mongoose.model<IMovie, IMovieModel>('Movie',MovieSchema)

Const MovieRunsModel

MovieRunsModel: IMovieRunModel = mongoose.model<IMovieRun, IMovieRunModel>('movierun',MovieRunsSchema)

Const MovieRunsSchema

MovieRunsSchema: Schema<any> = new mongoose.Schema({__v: { type: Number, select: false },type: { type: String, default: 'Normal' },language: { type: String, default: 'Spanish' },subtitles: { type: String, default: null },'3d': { type: Boolean, default: false },showTimes: {'Mon-Thu': [Date],'Mon-Fri': [Date],Friday: [Date],Saturday: [Date],Sunday: [Date],},})

Const MovieSchema

MovieSchema: Schema<any> = new mongoose.Schema({__v: { type: Number, select: false },movieId: { type: String, unique: true },title: { type: String, index: true },genre: { type: [String] },rating: { type: String },runtime: { type: Number },synopsis: { type: String },releaseDate: { type: Date },nowShowing: { type: Boolean },staring: { type: [ActorSchema] },})

Const TheatreModel

TheatreModel: ITheatreModel = mongoose.model<ITheatre, ITheatreModel>('Theatre',TheatreSchema)

Const TheatreSchema

TheatreSchema: Schema<any> = new mongoose.Schema({__v: { type: Number, select: false },name: { type: String },slug: { type: String, unique: true },city: { type: String },address: { type: String },phone: { type: String },amenities: {cxc: { type: Boolean, default: false },imax: { type: Boolean, default: false },'3d': { type: Boolean, default: false },'4dx': { type: Boolean, default: false },atm: { type: Boolean, default: false },accessible: { type: Boolean, default: false },partyRoom: { type: Boolean, default: false },gameRoom: { type: Boolean, default: false },stadiumTheatre: { type: Boolean, default: false },powerGenerator: { type: Boolean, default: false },},runs: { type: [MovieRunsSchema] },})

Const cli

cli: Result = meow(`Usage$ ts-node src/tasksOptions--now-showing, --now Scrape movies now showing--coming-soon, --soon Scrape movies coming soon--save, Store results in MongoDBExamples$ ts-node src/tasks --now --save`,{flags: {nowShowing: {type: 'boolean',alias: 'now',},comingSoon: {type: 'boolean',alias: 'soon',},save: {type: 'boolean',},},})

Const database

database: string = process.env.DATABASE_NAME || 'cc-api'

Const dbUrl

dbUrl: undefined | string = process.env.NODE_ENV === 'production'? process.env.PRODUCTION_DB_URI: `mongodb://${host}:${port}/${database}`

Const fakeNowShowing

fakeNowShowing: any = require('../../tests/data/now-showing.json')

Const host

host: string = process.env.DATABASE_HOST || 'localhost'

Const instance

instance: AxiosInstance = axios.create({baseURL: CC_URL,headers: { 'X-CC-API': API_GIT_URL },})

Let plugins

plugins: any[] = [require('@hapi/inert'),require('@hapi/vision'),jsonApiEnforcer,logger,version,]

Const port

port: string = process.env.DATABASE_PORT || '27017'

Const routes

routes: (object | object | object | object)[] = [...nowShowingRoutes,...theatreRoutes,...comingSoonRoutes,...movieRoutes,...movieRunRoutes,]

Let server

server: any

Functions

default

  • default(__namedParameters: object): Promise<object>

getAddress

  • getAddress(html: string): Promise<string>

getAmenities

  • getAmenities(html: string): Promise<object>

getDates

  • getDates(__namedParameters: object): DateTime[]

getFridayDays

  • getFridayDays(): DateTime[]

getGenres

  • getGenres(movieDetails: string[]): string[]

getMondayToFridayDays

  • getMondayToFridayDays(): DateTime[]

getMondayToThursdayDays

  • getMondayToThursdayDays(): DateTime[]

getMovieDetails

  • getMovieDetails(__namedParameters: object): object
  • Parameters

    • __namedParameters: object
      • movieDetailsArr: string[]
      • movieHtml: string

    Returns object

    • genre: string[]
    • rating: string
    • releaseDate: string
    • runtime: number
    • synopsis: null | string
    • title: string

getMovieTimeData

  • getMovieTimeData(movieTimeHtml: string): string[][]

getName

  • getName(html: string): Promise<string>

getPhone

  • getPhone(html: string): Promise<string>

getRating

  • getRating(movieDetails: string[]): string

getReleaseDate

  • getReleaseDate(movieDetails: string[]): string

getRuntime

  • getRuntime(movieDetails: string[]): number

getSaturdayDays

  • getSaturdayDays(): DateTime[]

getSubtitleLanguage

  • getSubtitleLanguage(subtitleText: string): string
  • Obtains the subtitle language from a text which may contain it.

    Parameters

    • subtitleText: string

      The subtitle text portion obtained from parsing a movie run.

    Returns string

    The subtitle language (ex: Spanish | English)

getSundayDays

  • getSundayDays(): DateTime[]

getSynopsis

  • getSynopsis(movieDetails: string[]): null | string

getTheatreData

  • getTheatreData(instance: AxiosInstance, slug: string): Promise<object>

getTheatres

  • getTheatres(instance: AxiosInstance): Promise<string[]>

getTitle

  • getTitle(movieHtml: string): string

parseRedisUrl

  • parseRedisUrl(redisUrl: string | null): object | object

saveToDB

  • Saves movie task data generated in task scripts to the database.

    Parameters

    • movies: IMovieTaskData[]

      Array of movie task data.

    • flags: object

      Flags passed from the CLI to meow.

      • [name: string]: any

    Returns Promise<void>

scrapeTheatreMovieRuns

  • scrapeTheatreMovieRuns(theatreSlug: string, instance: AxiosInstance): Promise<object[]>

stripTags

  • stripTags(elem: string): string
  • Removes whitespace from the start and end of an HTML element and also removes
    tags.

    Parameters

    • elem: string

      The HTML element object to strip.

    Returns string

    The elem object trimmed and without
    tags.

trimFormatButtonText

  • trimFormatButtonText(buttonText: string): object

Object literals

Const alternativeTheatreRoute

alternativeTheatreRoute: object

path

path: string = "/theaters/{theatreSlug?}"

Const comingSoonRoute

comingSoonRoute: object

method

method: string = "GET"

path

path: string = "/coming-soon"

handler

  • handler(): object

options

options: object

description

description: string = "Displays the upcoming movies"

notes

notes: string = "Updated every day at 1AM UTC."

tags

tags: string[] = ['api', 'home', 'coming-soon']

Const homePage

homePage: object

path

path: string = "/"

Const jsonApiEnforcer

jsonApiEnforcer: object

options

options: object

Type declaration

plugin

plugin: any = require('@gar/hapi-json-api')

Const loggerPlugin

loggerPlugin: object

plugin

plugin: any = require('@hapi/good')

options

options: object

ops

ops: object

interval

interval: number = 1000

reporters

reporters: object

consoleReporter

consoleReporter: (string | object | object)[] = [{module: '@hapi/good-squeeze',name: 'Squeeze',args: [{error: '*',log: '*',response: '*',request: '*',},],},{module: '@hapi/good-console',},'stdout',]

Const movieRoute

movieRoute: object

handler

handler: (Anonymous function) = movieController

method

method: string = "GET"

path

path: string = "/movies/{movieId?}"

options

options: object

description

description: string = "Get movies"

notes

notes: string = "Returns an array or an instance of movie details"

tags

tags: string[] = ['api', 'movie']

validate

validate: object

params

params: ObjectSchema<Object> = Joi.object({movieId: Joi.string().max(10).regex(/^\d+$/).optional().example('6833').description('The movie identifier. A numeric string.'),})

Const movieRunsDefaults

movieRunsDefaults: object

handler

handler: (Anonymous function) = movieRunController

method

method: string = "GET"

path

path: string = "/movie-runs/{movieRunId?}"

options

options: object

description

description: string = "Displays movie details."

notes

notes: string = "Updated every day at 1AM UTC."

tags

tags: string[] = ['api', 'movie-runs', 'movies']

plugins

plugins: object

hapi-swagger

hapi-swagger: object

Type declaration

validate

validate: object

params

params: ObjectSchema<Object> = Joi.object({movieRunId: Joi.string().max(24).regex(/^[0-9a-fA-F]{24}$/).optional().example('54759eb3c090d83494e2d804').description('The movie-run identifier. A MongoDB ObjectID.'),})

Const nowShowingDefaults

nowShowingDefaults: object

method

method: string = "GET"

path

path: string = "/now-showing"

handler

  • handler(): any

options

options: object

description

description: string = "Displays the movies that are featured as "now showing"."

notes

notes: string = "Updated every day at 1AM UTC."

tags

tags: string[] = ['api', 'home', 'now-showing']

Const nowShowingRoute

nowShowingRoute: object

Const rateLimitorPlugin

rateLimitorPlugin: object

plugin

plugin: any = require('hapi-rate-limitor')

options

options: object

duration

duration: number = 60 * 1000

max

max: number = 60

namespace

namespace: string = "hapi-rate-limitor"

redis

redis: object | object = parseRedisUrl(process.env.REDIS_URL || null)

Const sentryErrorPlugin

sentryErrorPlugin: object

options

options: object

Type declaration

plugin

plugin: any = require('hapi-sentry')

Const swaggerPlugin

swaggerPlugin: object

plugin

plugin: any = require('hapi-swagger')

options

options: object

documentationPage

documentationPage: boolean = true

documentationPath

documentationPath: string = "/docs"

swaggerUI

swaggerUI: boolean = true

tags

tags: object[] = [{name: 'movies',description: 'API movies interface.',},{name: 'theatres',description: 'API theatres interface.',},{name: 'theaters',description: 'API theatres interface.',},]

info

info: object

description

description: string = "Carribean Cinemas API Documentation"

title

title: string = "CC API"

version

version: string = "0.1"

Const theatreDefaults

theatreDefaults: object

handler

handler: (Anonymous function) = theatreController

method

method: string = "GET"

path

path: string = "/theatres/{theatreSlug?}"

options

options: object

description

description: string = "Get theatres"

notes

notes: string = "Returns an array or an instance of theatre details"

tags

tags: string[] = ['api', 'theatre']

validate

validate: object

params

params: ObjectSchema<Object> = Joi.object({theatreSlug: Joi.string().max(128).regex(/[a-z]+(-[a-z])*$/).optional().example('san-patricio').description('The theatre identifier. Usually a lowercase representation of the theatre name with dashes instead of spaces.'),})

Const theatreRoute

theatreRoute: object

Const versionPlugin

versionPlugin: object

plugin

plugin: any = require('hapi-api-version')

options

options: object

defaultVersion

defaultVersion: number = 1

validVersions

validVersions: number[] = [1]

vendorName

vendorName: string = "cc-api"

Legend

  • Module
  • Object literal
  • Variable
  • Function
  • Function with type parameter
  • Index signature
  • Type alias
  • Type alias with type parameter
  • Enumeration
  • Enumeration member
  • Property
  • Method
  • Interface
  • Interface with type parameter
  • Constructor
  • Property
  • Method
  • Index signature
  • Class
  • Class with type parameter
  • Constructor
  • Property
  • Method
  • Accessor
  • Index signature
  • Inherited constructor
  • Inherited property
  • Inherited method
  • Inherited accessor
  • Protected property
  • Protected method
  • Protected accessor
  • Private property
  • Private method
  • Private accessor
  • Static property
  • Static method

Generated using TypeDoc