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 <https://www.gnu.org/licenses/>.
*/
-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 <https://www.gnu.org/licenses/>.
*/
-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 <https://www.gnu.org/licenses/>.
*/
-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";
|