You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
3.9 KiB
145 lines
3.9 KiB
import {
|
|
FastifyInstance,
|
|
RouteShorthandOptions,
|
|
Plugin,
|
|
DefaultQuery,
|
|
DefaultParams,
|
|
DefaultHeaders,
|
|
DefaultBody,
|
|
JSONSchema,
|
|
} from 'fastify'
|
|
import { Server, IncomingMessage, ServerResponse } from 'http'
|
|
import request from 'request'
|
|
import { PluginOptions, GiphyResponse } from '../../types'
|
|
|
|
interface FetchOptions {
|
|
url: string
|
|
params?: string[][]
|
|
method?: string
|
|
}
|
|
|
|
const paramsToString = (params: string[][]) => params.map(p => p.join('=')).join('&')
|
|
|
|
const giphyGifSchema: JSONSchema = {
|
|
type: 'object',
|
|
properties: {
|
|
type: { type: 'string' },
|
|
id: { type: 'string' },
|
|
slug: { type: 'string' },
|
|
url: { type: 'string' },
|
|
bitly_url: { type: 'string' },
|
|
embed_url: { type: 'string' },
|
|
title: { type: 'string' },
|
|
images: {
|
|
type: 'object',
|
|
properties: {
|
|
fixed_height: {
|
|
type: 'object',
|
|
properties: {
|
|
url: { type: 'string' },
|
|
},
|
|
},
|
|
fixed_height_still: {
|
|
type: 'object',
|
|
properties: {
|
|
url: { type: 'string' },
|
|
},
|
|
},
|
|
fixed_height_downsampled: {
|
|
type: 'object',
|
|
properties: {
|
|
url: { type: 'string' },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
async function fetch<T = any>(options: FetchOptions) {
|
|
const { url, params = [], method = 'get' } = options
|
|
const uri = params.length > 0 ? `${url}?${paramsToString(params)}` : url
|
|
|
|
return new Promise<T>((resolve, reject) => {
|
|
request({
|
|
uri,
|
|
method,
|
|
json: true,
|
|
}, function(error, response, body) {
|
|
if (error) {
|
|
reject(error)
|
|
return
|
|
}
|
|
|
|
resolve(body)
|
|
})
|
|
})
|
|
}
|
|
|
|
function gifHomeRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) {
|
|
const options: RouteShorthandOptions = {
|
|
schema: {
|
|
response: {
|
|
200: {
|
|
type: 'array',
|
|
items: giphyGifSchema,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
server.get<DefaultQuery, DefaultParams, DefaultHeaders, DefaultBody>('/api/gifs/home', options, async (request, reply) => {
|
|
const response = await fetch<GiphyResponse>({
|
|
url: `${process.env.GIPHY_API_ENDPOINT!}/v1/gifs/trending`,
|
|
params: [['api_key', process.env.GIPHY_API_KEY!], ['limit', '20']],
|
|
})
|
|
|
|
return response.data
|
|
})
|
|
}
|
|
|
|
function gifSearchRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) {
|
|
interface Query {
|
|
q: string
|
|
}
|
|
|
|
const options: RouteShorthandOptions = {
|
|
schema: {
|
|
querystring: {
|
|
type: 'object',
|
|
properties: {
|
|
q: { type: 'string' },
|
|
},
|
|
},
|
|
response: {
|
|
200: {
|
|
type: 'array',
|
|
items: giphyGifSchema,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
server.get<Query, DefaultParams, DefaultHeaders, DefaultBody>('/api/gifs/search', options, async (request, reply) => {
|
|
const q = request.query.q ? request.query.q.trim() : ''
|
|
|
|
if (q.length < 3) {
|
|
reply.code(400)
|
|
return
|
|
}
|
|
|
|
const response = await fetch<GiphyResponse>({
|
|
url: `${process.env.GIPHY_API_ENDPOINT!}/v1/gifs/search`,
|
|
params: [['api_key', process.env.GIPHY_API_KEY!], ['limit', '20'], ['q', q]],
|
|
})
|
|
|
|
return response.data
|
|
})
|
|
}
|
|
|
|
const plugin: Plugin<Server, IncomingMessage, ServerResponse, PluginOptions> = async server => {
|
|
gifHomeRoute(server)
|
|
gifSearchRoute(server)
|
|
}
|
|
|
|
export default plugin
|