mirror of
https://github.com/spacebarchat/server.git
synced 2026-07-21 00:20:55 +00:00
Migrate trending gifs to providers
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -26,4 +26,20 @@ public class GifItem {
|
||||
|
||||
[JsonPropertyName("height")]
|
||||
public int Height { get; set; }
|
||||
}
|
||||
|
||||
public class TrendingGifsResult {
|
||||
[JsonPropertyName("categories")]
|
||||
public List<CategoryEntry> Categories { get; set; }
|
||||
|
||||
[JsonPropertyName("gifs")]
|
||||
public List<GifItem> Gifs { get; set; }
|
||||
|
||||
public class CategoryEntry {
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonPropertyName("src")]
|
||||
public string Source { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -28,10 +28,13 @@ public class GifTests(ITestOutputHelper testOutputHelper, TestFixture fixture) :
|
||||
Client = await _userAbstraction.GetSharedUser();
|
||||
}
|
||||
|
||||
// wish this could just be a single string.... MEmberData requires returning an array spanning the argument count...
|
||||
public static IEnumerable<string[]> GifProviders() => [["tenor"]];
|
||||
|
||||
public static IEnumerable<object[]> GifSearchTestMatrix() {
|
||||
foreach (var query in (string[])["meow", "meowmeow"])
|
||||
foreach (var provider in (string[])["tenor"])
|
||||
yield return [query, provider];
|
||||
foreach (var provider in GifProviders())
|
||||
yield return [query, provider[0]];
|
||||
}
|
||||
|
||||
[Theory, MemberData(nameof(GifSearchTestMatrix))]
|
||||
@@ -50,4 +53,28 @@ public class GifTests(ITestOutputHelper testOutputHelper, TestFixture fixture) :
|
||||
Assert.NotEqual(0, gif.Height);
|
||||
});
|
||||
}
|
||||
|
||||
[Theory, MemberData(nameof(GifProviders))]
|
||||
public async Task GetTrendingCategories(string provider) {
|
||||
var resp = await Assert.HttpSuccess(await Client.ApiHttpClient.GetAsync($"gifs/trending?provider={provider}", TestContext.Current.CancellationToken));
|
||||
var respContent = await resp.Content.ReadFromJsonAsync<TrendingGifsResult>(cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.True(respContent!.Categories.Count > 0, "respContent.Categories.Count > 0");
|
||||
Assert.True(respContent.Gifs.Count > 0, "respContent.Gifs.Count > 0");
|
||||
|
||||
Assert.All(respContent.Categories, cat => {
|
||||
Assert.StringNotNullOrWhitespace(cat.Name);
|
||||
Assert.StringNotNullOrWhitespace(cat.Source);
|
||||
});
|
||||
|
||||
Assert.All(respContent.Gifs, gif => {
|
||||
Assert.StringNotNullOrWhitespace(gif.Id);
|
||||
Assert.StringNotNullOrWhitespace(gif.GifSource);
|
||||
Assert.StringNotNullOrWhitespace(gif.Preview);
|
||||
Assert.StringNotNullOrWhitespace(gif.Source);
|
||||
Assert.StringNotNullOrWhitespace(gif.Url);
|
||||
Assert.NotEqual(0, gif.Width);
|
||||
Assert.NotEqual(0, gif.Height);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,9 @@
|
||||
import { route } from "@spacebar/api/util/handlers/route";
|
||||
import { getGifApiKey, parseGifResult } from "@spacebar/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { TenorCategoriesResults, TenorTrendingResults } from "@spacebar/schemas";
|
||||
import { TenorCategoriesResults, TenorTrendingResponse, TenorTrendingResults } from "@spacebar/schemas";
|
||||
import { GifProviderManager } from "@spacebar/util/util/integrations/gifProviders/GifProviderManager";
|
||||
import trendingGifs from "@spacebar/api/routes/gifs/trending-gifs";
|
||||
|
||||
const router = Router({ mergeParams: true });
|
||||
|
||||
@@ -31,6 +33,10 @@ router.get(
|
||||
type: "string",
|
||||
description: "Locale",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
description: "Provider to use",
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
@@ -39,34 +45,17 @@ router.get(
|
||||
},
|
||||
}),
|
||||
async (req: Request, res: Response) => {
|
||||
// TODO: Custom providers
|
||||
// TODO: return gifs as mp4
|
||||
// const { media_format, locale } = req.query;
|
||||
const { locale } = req.query;
|
||||
const provider = GifProviderManager.getProvider((req.query.provider as string) ?? "tenor");
|
||||
|
||||
const apiKey = getGifApiKey();
|
||||
|
||||
const [responseSource, trendGifSource] = await Promise.all([
|
||||
fetch(`https://g.tenor.com/v1/categories?locale=${locale}&key=${apiKey}`, {
|
||||
method: "get",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
}),
|
||||
fetch(`https://g.tenor.com/v1/trending?locale=${locale}&key=${apiKey}`, {
|
||||
method: "get",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
}),
|
||||
const [trendingCategories, trendingGifs] = await Promise.all([
|
||||
provider.getTrendingCategories(req.query as typeof provider.getTrendingCategories.arguments),
|
||||
provider.getTrendingGifs(req.query as typeof provider.getTrendingCategories.arguments),
|
||||
]);
|
||||
|
||||
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);
|
||||
categories: trendingCategories,
|
||||
gifs: trendingGifs,
|
||||
} satisfies TenorTrendingResponse).status(200);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -82,8 +82,13 @@ export interface GifResponse {
|
||||
preview: string;
|
||||
}
|
||||
|
||||
export interface GifTrendingCategory {
|
||||
name: string;
|
||||
src: string;
|
||||
}
|
||||
|
||||
export interface TenorTrendingResponse {
|
||||
categories: TenorCategoriesResults;
|
||||
categories: GifTrendingCategory[];
|
||||
gifs: GifResponse[];
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { GifsResponse } from "@spacebar/schemas";
|
||||
import { GifsResponse, GifTrendingCategory } from "@spacebar/schemas";
|
||||
|
||||
export interface IGifProvider {
|
||||
id: string;
|
||||
@@ -24,4 +24,6 @@ export interface IGifProvider {
|
||||
|
||||
init(): Promise<void>;
|
||||
search(query: { q: string; limit?: number; media_format: string; locale: string }): Promise<GifsResponse>;
|
||||
getTrendingCategories(query: { media_format: string; locale: string }): Promise<GifTrendingCategory[]>;
|
||||
getTrendingGifs(query: { q: string; limit?: number; media_format: string; locale: string }): Promise<GifsResponse>;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
import type { IGifProvider } from "../IGifProvider";
|
||||
import { TenorGif, GifsResponse } from "@spacebar/schemas";
|
||||
import { TenorGif, GifsResponse, TenorCategoriesResults, GifTrendingCategory } from "@spacebar/schemas";
|
||||
import { Config, getGifApiKey, parseGifResult } from "@spacebar/util";
|
||||
|
||||
export default class TenorGifProvider implements IGifProvider {
|
||||
@@ -45,6 +45,30 @@ export default class TenorGifProvider implements IGifProvider {
|
||||
return results.map(this.convertGifResult);
|
||||
}
|
||||
|
||||
async getTrendingCategories(query: { media_format: string; locale: string }): Promise<GifTrendingCategory[]> {
|
||||
const response = await fetch(`https://g.tenor.com/v1/categories?locale=${query.locale}&key=${this.#apiKey}`, {
|
||||
method: "get",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
|
||||
const { tags } = (await response.json()) as TenorCategoriesResults;
|
||||
|
||||
return tags.map((x) => ({
|
||||
name: x.searchterm,
|
||||
src: x.image,
|
||||
})) satisfies GifTrendingCategory[];
|
||||
}
|
||||
|
||||
async getTrendingGifs(query: { media_format: string; locale: string }): Promise<GifsResponse> {
|
||||
const response = await fetch(`https://g.tenor.com/v1/trending?media_format=${query.media_format}&locale=${query.locale}&key=${this.#apiKey}`, {
|
||||
method: "get",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
|
||||
const { results } = (await response.json()) as { results: TenorGif[] };
|
||||
return results.map(this.convertGifResult);
|
||||
}
|
||||
|
||||
private convertGifResult(result: TenorGif) {
|
||||
return {
|
||||
id: result.id,
|
||||
|
||||
Reference in New Issue
Block a user