From 0dc5b19bd87875f146362e042e976958a047192e Mon Sep 17 00:00:00 2001 From: Puyodead1 Date: Fri, 24 Mar 2023 18:57:44 -0400 Subject: gifs and query params --- src/api/routes/gifs/search.ts | 65 ++++++++++---- src/api/routes/gifs/trending-gifs.ts | 60 +++++++++---- src/api/routes/gifs/trending.ts | 159 +++++++++++++++-------------------- src/api/util/handlers/route.ts | 8 ++ src/util/schemas/responses/Tenor.ts | 72 ++++++++++++++++ src/util/schemas/responses/index.ts | 1 + 6 files changed, 236 insertions(+), 129 deletions(-) create mode 100644 src/util/schemas/responses/Tenor.ts (limited to 'src') diff --git a/src/api/routes/gifs/search.ts b/src/api/routes/gifs/search.ts index fb99374b..b51bba37 100644 --- a/src/api/routes/gifs/search.ts +++ b/src/api/routes/gifs/search.ts @@ -16,34 +16,63 @@ along with this program. If not, see . */ -import { Router, Response, Request } from "express"; +import { route } from "@spacebar/api"; +import { TenorMediaTypes } from "@spacebar/util"; +import { Request, Response, Router } from "express"; import fetch from "node-fetch"; import ProxyAgent from "proxy-agent"; -import { route } from "@spacebar/api"; import { getGifApiKey, parseGifResult } from "./trending"; const router = Router(); -router.get("/", route({}), async (req: Request, res: Response) => { - // TODO: Custom providers - const { q, media_format, locale } = req.query; +router.get( + "/", + route({ + query: { + q: { + type: "string", + required: true, + description: "Search query", + }, + media_format: { + type: "string", + description: "Media format", + values: Object.keys(TenorMediaTypes).filter((key) => + isNaN(Number(key)), + ), + }, + locale: { + type: "string", + description: "Locale", + }, + }, + responses: { + 200: { + body: "TenorGifsResponse", + }, + }, + }), + async (req: Request, res: Response) => { + // TODO: Custom providers + const { q, media_format, locale } = req.query; - const apiKey = getGifApiKey(); + const apiKey = getGifApiKey(); - const agent = new ProxyAgent(); + const agent = new ProxyAgent(); - const response = await fetch( - `https://g.tenor.com/v1/search?q=${q}&media_format=${media_format}&locale=${locale}&key=${apiKey}`, - { - agent, - method: "get", - headers: { "Content-Type": "application/json" }, - }, - ); + const response = await fetch( + `https://g.tenor.com/v1/search?q=${q}&media_format=${media_format}&locale=${locale}&key=${apiKey}`, + { + agent, + method: "get", + headers: { "Content-Type": "application/json" }, + }, + ); - const { results } = await response.json(); + const { results } = await response.json(); - res.json(results.map(parseGifResult)).status(200); -}); + res.json(results.map(parseGifResult)).status(200); + }, +); export default router; diff --git a/src/api/routes/gifs/trending-gifs.ts b/src/api/routes/gifs/trending-gifs.ts index 238a2abd..899250cf 100644 --- a/src/api/routes/gifs/trending-gifs.ts +++ b/src/api/routes/gifs/trending-gifs.ts @@ -16,34 +16,58 @@ along with this program. If not, see . */ -import { Router, Response, Request } from "express"; +import { route } from "@spacebar/api"; +import { TenorMediaTypes } from "@spacebar/util"; +import { Request, Response, Router } from "express"; import fetch from "node-fetch"; import ProxyAgent from "proxy-agent"; -import { route } from "@spacebar/api"; import { getGifApiKey, parseGifResult } from "./trending"; const router = Router(); -router.get("/", route({}), async (req: Request, res: Response) => { - // TODO: Custom providers - const { media_format, locale } = req.query; +router.get( + "/", + route({ + query: { + media_format: { + type: "string", + description: "Media format", + values: Object.keys(TenorMediaTypes).filter((key) => + isNaN(Number(key)), + ), + }, + locale: { + type: "string", + description: "Locale", + }, + }, + responses: { + 200: { + body: "TenorGifsResponse", + }, + }, + }), + async (req: Request, res: Response) => { + // TODO: Custom providers + const { media_format, locale } = req.query; - const apiKey = getGifApiKey(); + const apiKey = getGifApiKey(); - const agent = new ProxyAgent(); + const agent = new ProxyAgent(); - const response = await fetch( - `https://g.tenor.com/v1/trending?media_format=${media_format}&locale=${locale}&key=${apiKey}`, - { - agent, - method: "get", - headers: { "Content-Type": "application/json" }, - }, - ); + const response = await fetch( + `https://g.tenor.com/v1/trending?media_format=${media_format}&locale=${locale}&key=${apiKey}`, + { + agent, + method: "get", + headers: { "Content-Type": "application/json" }, + }, + ); - const { results } = await response.json(); + const { results } = await response.json(); - res.json(results.map(parseGifResult)).status(200); -}); + res.json(results.map(parseGifResult)).status(200); + }, +); export default router; diff --git a/src/api/routes/gifs/trending.ts b/src/api/routes/gifs/trending.ts index 5cccdb2d..3c2ab6ab 100644 --- a/src/api/routes/gifs/trending.ts +++ b/src/api/routes/gifs/trending.ts @@ -16,66 +16,21 @@ along with this program. If not, see . */ -import { Router, Response, Request } from "express"; -import fetch from "node-fetch"; -import ProxyAgent from "proxy-agent"; import { route } from "@spacebar/api"; -import { Config } from "@spacebar/util"; +import { + Config, + TenorCategoriesResults, + TenorGif, + TenorTrendingResults, +} from "@spacebar/util"; +import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; +import fetch from "node-fetch"; +import ProxyAgent from "proxy-agent"; const router = Router(); -// TODO: Move somewhere else -enum TENOR_GIF_TYPES { - gif, - mediumgif, - tinygif, - nanogif, - mp4, - loopedmp4, - tinymp4, - nanomp4, - webm, - tinywebm, - nanowebm, -} - -type TENOR_MEDIA = { - preview: string; - url: string; - dims: number[]; - size: number; -}; - -type TENOR_GIF = { - created: number; - hasaudio: boolean; - id: string; - media: { [type in keyof typeof TENOR_GIF_TYPES]: TENOR_MEDIA }[]; - tags: string[]; - title: string; - itemurl: string; - hascaption: boolean; - url: string; -}; - -type TENOR_CATEGORY = { - searchterm: string; - path: string; - image: string; - name: string; -}; - -type TENOR_CATEGORIES_RESULTS = { - tags: TENOR_CATEGORY[]; -}; - -type TENOR_TRENDING_RESULTS = { - next: string; - results: TENOR_GIF[]; -}; - -export function parseGifResult(result: TENOR_GIF) { +export function parseGifResult(result: TenorGif) { return { id: result.id, title: result.title, @@ -97,45 +52,63 @@ export function getGifApiKey() { return apiKey; } -router.get("/", route({}), async (req: Request, res: Response) => { - // TODO: Custom providers - // TODO: return gifs as mp4 - // const { media_format, locale } = req.query; - const { locale } = req.query; - - const apiKey = getGifApiKey(); - - const agent = new ProxyAgent(); - - const [responseSource, trendGifSource] = await Promise.all([ - fetch( - `https://g.tenor.com/v1/categories?locale=${locale}&key=${apiKey}`, - { - agent, - method: "get", - headers: { "Content-Type": "application/json" }, +router.get( + "/", + route({ + query: { + locale: { + type: "string", + description: "Locale", }, - ), - fetch( - `https://g.tenor.com/v1/trending?locale=${locale}&key=${apiKey}`, - { - agent, - method: "get", - headers: { "Content-Type": "application/json" }, + }, + responses: { + 200: { + body: "TenorTrendingResponse", }, - ), - ]); - - const { tags } = (await responseSource.json()) as TENOR_CATEGORIES_RESULTS; - const { results } = (await trendGifSource.json()) as TENOR_TRENDING_RESULTS; - - res.json({ - categories: tags.map((x) => ({ - name: x.searchterm, - src: x.image, - })), - gifs: [parseGifResult(results[0])], - }).status(200); -}); + }, + }), + async (req: Request, res: Response) => { + // TODO: Custom providers + // TODO: return gifs as mp4 + // const { media_format, locale } = req.query; + const { locale } = req.query; + + const apiKey = getGifApiKey(); + + const agent = new ProxyAgent(); + + const [responseSource, trendGifSource] = await Promise.all([ + fetch( + `https://g.tenor.com/v1/categories?locale=${locale}&key=${apiKey}`, + { + agent, + method: "get", + headers: { "Content-Type": "application/json" }, + }, + ), + fetch( + `https://g.tenor.com/v1/trending?locale=${locale}&key=${apiKey}`, + { + agent, + method: "get", + headers: { "Content-Type": "application/json" }, + }, + ), + ]); + + const { tags } = + (await responseSource.json()) as TenorCategoriesResults; + const { results } = + (await trendGifSource.json()) as TenorTrendingResults; + + res.json({ + categories: tags.map((x) => ({ + name: x.searchterm, + src: x.image, + })), + gifs: [parseGifResult(results[0])], + }).status(200); + }, +); export default router; diff --git a/src/api/util/handlers/route.ts b/src/api/util/handlers/route.ts index 331ac0c2..2416b73f 100644 --- a/src/api/util/handlers/route.ts +++ b/src/api/util/handlers/route.ts @@ -62,6 +62,14 @@ export interface RouteOptions { event?: EVENT | EVENT[]; summary?: string; description?: string; + query?: { + [key: string]: { + type: string; + required?: boolean; + description?: string; + values?: string[]; + }; + }; // test?: { // response?: RouteResponse; // body?: unknown; diff --git a/src/util/schemas/responses/Tenor.ts b/src/util/schemas/responses/Tenor.ts new file mode 100644 index 00000000..9dddf9d0 --- /dev/null +++ b/src/util/schemas/responses/Tenor.ts @@ -0,0 +1,72 @@ +export enum TenorMediaTypes { + gif, + mediumgif, + tinygif, + nanogif, + mp4, + loopedmp4, + tinymp4, + nanomp4, + webm, + tinywebm, + nanowebm, +} + +export type TenorMedia = { + preview: string; + url: string; + dims: number[]; + size: number; +}; + +export type TenorGif = { + created: number; + hasaudio: boolean; + id: string; + media: { [type in keyof typeof TenorMediaTypes]: TenorMedia }[]; + tags: string[]; + title: string; + itemurl: string; + hascaption: boolean; + url: string; +}; + +export type TenorCategory = { + searchterm: string; + path: string; + image: string; + name: string; +}; + +export type TenorCategoriesResults = { + tags: TenorCategory[]; +}; + +export type TenorTrendingResults = { + next: string; + results: TenorGif[]; + locale: string; +}; + +export type TenorSearchResults = { + next: string; + results: TenorGif[]; +}; + +export interface TenorGifResponse { + id: string; + title: string; + url: string; + src: string; + gif_src: string; + width: number; + height: number; + preview: string; +} + +export interface TenorTrendingResponse { + categories: TenorCategoriesResults; + gifs: TenorGifResponse[]; +} + +export type TenorGifsResponse = TenorGifResponse[]; diff --git a/src/util/schemas/responses/index.ts b/src/util/schemas/responses/index.ts index 49e8053b..30949f7f 100644 --- a/src/util/schemas/responses/index.ts +++ b/src/util/schemas/responses/index.ts @@ -13,6 +13,7 @@ export * from "./GatewayBotResponse"; export * from "./GatewayResponse"; export * from "./GenerateRegistrationTokensResponse"; export * from "./LocationMetadataResponse"; +export * from "./Tenor"; export * from "./TokenResponse"; export * from "./UserProfileResponse"; export * from "./UserRelationsResponse"; -- cgit 1.4.1