diff --git a/api/src/routes/categories.ts b/api/src/routes/categories.ts new file mode 100644 index 00000000..58322676 --- /dev/null +++ b/api/src/routes/categories.ts @@ -0,0 +1,27 @@ +import { Router, Response, Request } from "express"; +import { route } from "@fosscord/api"; + +const router = Router(); + +router.get("/", route({}), (req: Request, res: Response) => { + // TODO: + // Load categories from db instead + + const { locale, primary_only } = req.query; + + let out; + + switch (locale) { + case "en-US": + switch (primary_only) { + case "false": + out = [{"id": 0, "is_primary": true, "name": "General"}, {"id": 10, "is_primary": true, "name": "Travel & Food"}, {"id": 15, "is_primary": false, "name": "Esports"}, {"id": 30, "is_primary": false, "name": "LFG"}, {"id": 32, "is_primary": false, "name": "Theorycraft"}, {"id": 36, "is_primary": false, "name": "Business"}, {"id": 39, "is_primary": false, "name": "Fandom"}, {"id": 43, "is_primary": true, "name": "Emoji"}, {"id": 18, "is_primary": false, "name": "Books"}, {"id": 23, "is_primary": false, "name": "Podcasts"}, {"id": 28, "is_primary": false, "name": "Investing"}, {"id": 7, "is_primary": true, "name": "Sports"}, {"id": 13, "is_primary": true, "name": "Other"}, {"id": 2, "is_primary": true, "name": "Music"}, {"id": 3, "is_primary": true, "name": "Entertainment"}, {"id": 4, "is_primary": true, "name": "Creative Arts"}, {"id": 6, "is_primary": true, "name": "Education"}, {"id": 9, "is_primary": true, "name": "Relationships & Identity"}, {"id": 11, "is_primary": true, "name": "Fitness & Health"}, {"id": 12, "is_primary": true, "name": "Finance"}, {"id": 45, "is_primary": false, "name": "Mobile"}, {"id": 16, "is_primary": false, "name": "Anime & Manga"}, {"id": 17, "is_primary": false, "name": "Movies & TV"}, {"id": 19, "is_primary": false, "name": "Art"}, {"id": 20, "is_primary": false, "name": "Writing"}, {"id": 22, "is_primary": false, "name": "Programming"}, {"id": 25, "is_primary": false, "name": "Memes"}, {"id": 27, "is_primary": false, "name": "Cryptocurrency"}, {"id": 31, "is_primary": false, "name": "Customer Support"}, {"id": 33, "is_primary": false, "name": "Events"}, {"id": 34, "is_primary": false, "name": "Roleplay"}, {"id": 37, "is_primary": false, "name": "Local Group"}, {"id": 38, "is_primary": false, "name": "Collaboration"}, {"id": 40, "is_primary": false, "name": "Wiki & Guide"}, {"id": 42, "is_primary": false, "name": "Subreddit"}, {"id": 1, "is_primary": true, "name": "Gaming"}, {"id": 5, "is_primary": true, "name": "Science & Tech"}, {"id": 8, "is_primary": true, "name": "Fashion & Beauty"}, {"id": 14, "is_primary": true, "name": "General Chatting"}, {"id": 21, "is_primary": false, "name": "Crafts, DIY, & Making"}, {"id": 48, "is_primary": false, "name": "Game Developer"}, {"id": 49, "is_primary": true, "name": "Bots"}, {"id": 24, "is_primary": false, "name": "Tabletop Games"}, {"id": 26, "is_primary": false, "name": "News & Current Events"}, {"id": 29, "is_primary": false, "name": "Studying & Teaching"}, {"id": 35, "is_primary": false, "name": "Content Creator"}, {"id": 44, "is_primary": false, "name": "Comics & Cartoons"}, {"id": 46, "is_primary": false, "name": "Console"}, {"id": 47, "is_primary": false, "name": "Charity & Nonprofit"}] + case "true": + out = [{"id": 0, "is_primary": true, "name": "General"}, {"id": 10, "is_primary": true, "name": "Travel & Food"}, {"id": 43, "is_primary": true, "name": "Emoji"}, {"id": 7, "is_primary": true, "name": "Sports"}, {"id": 13, "is_primary": true, "name": "Other"}, {"id": 2, "is_primary": true, "name": "Music"}, {"id": 3, "is_primary": true, "name": "Entertainment"}, {"id": 4, "is_primary": true, "name": "Creative Arts"}, {"id": 6, "is_primary": true, "name": "Education"}, {"id": 9, "is_primary": true, "name": "Relationships & Identity"}, {"id": 11, "is_primary": true, "name": "Fitness & Health"}, {"id": 12, "is_primary": true, "name": "Finance"}, {"id": 1, "is_primary": true, "name": "Gaming"}, {"id": 5, "is_primary": true, "name": "Science & Tech"}, {"id": 8, "is_primary": true, "name": "Fashion & Beauty"}, {"id": 14, "is_primary": true, "name": "General Chatting"}] + } + } + + res.json(out).status(200); +}); + +export default router; diff --git a/api/src/routes/discoverable-guilds.ts b/api/src/routes/discoverable-guilds.ts index 1cf56f84..a4559b59 100644 --- a/api/src/routes/discoverable-guilds.ts +++ b/api/src/routes/discoverable-guilds.ts @@ -6,15 +6,26 @@ import { route } from "@fosscord/api"; const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { - const { limit } = req.params; + const { limit, categories } = req.query; var showAllGuilds = Config.get().guild.showAllGuildsInDiscovery; // ! this only works using SQL querys // TODO: implement this with default typeorm query // const guilds = await Guild.find({ where: { features: "DISCOVERABLE" } }); //, take: Math.abs(Number(limit)) }); - const guilds = showAllGuilds - ? await Guild.find({ take: Math.abs(Number(limit || 20)) }) - : await Guild.find({ where: `"features" LIKE '%COMMUNITY%'`, take: Math.abs(Number(limit || 20)) }); - res.send({ guilds: guilds }); + let guilds; + let total; + switch (categories) { + case "1": + guilds = showAllGuilds + ? await Guild.find({ take: Math.abs(Number(limit || 24)) }) + : await Guild.find({ where: `"primary_category_id" = 1 AND "features" LIKE '%COMMUNITY%'`, take: Math.abs(Number(limit || 24)) }); + total = guilds.length; + default: + guilds = showAllGuilds + ? await Guild.find({ take: Math.abs(Number(limit || 24)) }) + : await Guild.find({ where: `"features" LIKE '%COMMUNITY%'`, take: Math.abs(Number(limit || 24)) }); + total = guilds.length; + } + res.send({ total: total, guilds: guilds, offset: 0, limit: limit}); }); export default router; diff --git a/api/src/routes/discovery.ts b/api/src/routes/discovery.ts deleted file mode 100644 index bc495d42..00000000 --- a/api/src/routes/discovery.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Router, Response, Request } from "express"; -import { route } from "@fosscord/api"; - -const router = Router(); - -router.get("/categories", route({}), (req: Request, res: Response) => { - // TODO: - //const { locale, primary_only } = req.query; - res.json([]).status(200); -}); - -export default router; diff --git a/api/src/routes/guild-recommendations.ts b/api/src/routes/guild-recommendations.ts index 503b19b7..47017a6f 100644 --- a/api/src/routes/guild-recommendations.ts +++ b/api/src/routes/guild-recommendations.ts @@ -6,14 +6,14 @@ import { route } from "@fosscord/api"; const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { - const { limit, personalization_disabled } = req.params; + const { limit, personalization_disabled } = req.query; var showAllGuilds = Config.get().guild.showAllGuildsInDiscovery; // ! this only works using SQL querys // TODO: implement this with default typeorm query // const guilds = await Guild.find({ where: { features: "DISCOVERABLE" } }); //, take: Math.abs(Number(limit)) }); const guilds = showAllGuilds - ? await Guild.find({ take: Math.abs(Number(limit || 20)) }) - : await Guild.find({ where: `"features" LIKE '%COMMUNITY%'`, take: Math.abs(Number(limit || 100)) }); + ? await Guild.find({ take: Math.abs(Number(limit || 24)) }) + : await Guild.find({ where: `"features" LIKE '%COMMUNITY%'`, take: Math.abs(Number(limit || 24)) }); res.send({ recommended_guilds: guilds }); }); diff --git a/bundle/package-lock.json b/bundle/package-lock.json index e8b99037..e763f22a 100644 --- a/bundle/package-lock.json +++ b/bundle/package-lock.json @@ -95,9 +95,10 @@ } }, "../api": { + "name": "@fosscord/api", "version": "1.0.0", "hasInstallScript": true, - "license": "ISC", + "license": "GPLV3", "dependencies": { "@babel/preset-env": "^7.15.8", "@babel/preset-typescript": "^7.15.0", @@ -158,8 +159,9 @@ } }, "../cdn": { + "name": "@fosscord/cdn", "version": "1.0.0", - "license": "ISC", + "license": "GPLV3", "dependencies": { "@aws-sdk/client-s3": "^3.36.1", "@aws-sdk/node-http-handler": "^3.36.0", @@ -200,9 +202,10 @@ } }, "../gateway": { + "name": "@fosscord/gateway", "version": "1.0.0", "hasInstallScript": true, - "license": "ISC", + "license": "GPLV3", "dependencies": { "@fosscord/util": "file:../util", "amqplib": "^0.8.0", diff --git a/bundle/package.json b/bundle/package.json index 456c89d7..e0ae6156 100644 --- a/bundle/package.json +++ b/bundle/package.json @@ -107,4 +107,4 @@ "ws": "^7.4.2", "nanocolors": "^0.2.12" } -} +} \ No newline at end of file diff --git a/util/src/entities/Categories.ts b/util/src/entities/Categories.ts new file mode 100644 index 00000000..2cf89dbc --- /dev/null +++ b/util/src/entities/Categories.ts @@ -0,0 +1,36 @@ +import { PrimaryColumn, Column, Entity} from "typeorm"; +import { BaseClassWithoutId } from "./BaseClass"; + +// TODO: categories: +// [{ +// "id": 16, +// "default": "Anime & Manga", +// "localizations": { +// "de": "Anime & Manga", +// "fr": "Anim\u00e9s et mangas", +// "ru": "\u0410\u043d\u0438\u043c\u0435 \u0438 \u043c\u0430\u043d\u0433\u0430" +// } +// }, +// "is_primary": false/true +// }] + +@Entity("categories") +export class Categories extends BaseClassWithoutId { // Not using snowflake + + @PrimaryColumn() + id: number; + + @Column() + default: string; + + @Column({ type: "simple-json", nullable: false }) + localizations: string; + + @Column() + is_primary: boolean; + +} + +export interface DefaultCategoryValue { // TODO: Load Default Discord Categories + +} \ No newline at end of file diff --git a/util/src/entities/Config.ts b/util/src/entities/Config.ts index 6993cc09..4da65b36 100644 --- a/util/src/entities/Config.ts +++ b/util/src/entities/Config.ts @@ -158,6 +158,7 @@ export interface ConfigValue { }; guild: { showAllGuildsInDiscovery: boolean; + homeDiscoveryUseRecommendation: boolean; // TODO: Recommendation, privacy concern? autoJoin: { enabled: boolean; guilds: string[]; @@ -354,6 +355,7 @@ export const DefaultConfigOptions: ConfigValue = { }, guild: { showAllGuildsInDiscovery: false, + homeDiscoveryUseRecommendation: false, autoJoin: { enabled: true, canLeave: true, diff --git a/util/src/entities/Guild.ts b/util/src/entities/Guild.ts index 6a1df4d6..65ba2ae2 100644 --- a/util/src/entities/Guild.ts +++ b/util/src/entities/Guild.ts @@ -17,28 +17,6 @@ import { Webhook } from "./Webhook"; // TODO: guild_scheduled_events // TODO: stage_instances // TODO: threads -// TODO: categories: -// [{ -// "id": 16, -// "name": { -// "default": "Anime & Manga", -// "localizations": { -// "de": "Anime & Manga", -// "fr": "Anim\u00e9s et mangas", -// "ru": "\u0410\u043d\u0438\u043c\u0435 \u0438 \u043c\u0430\u043d\u0433\u0430" -// } -// }, -// "is_primary": false -// }] -// TODO: -// primary_category :{ -// id: 1, -// name: { -// default: "Gaming", -// localizations: { de: "Gaming", fr: "Gaming", ru: "\u0418\u0433\u0440\u044b" }, -// is_primary: true, -// }, -// }; // TODO: // "keywords": [ // "Genshin Impact", @@ -107,6 +85,9 @@ export class Guild extends BaseClass { features: string[]; //TODO use enum //TODO: https://discord.com/developers/docs/resources/guild#guild-object-guild-features + @Column({ nullable: true }) + primary_category_id: number; + @Column({ nullable: true }) icon?: string; @@ -306,6 +287,7 @@ export class Guild extends BaseClass { default_message_notifications: 1, // defaults effect: setting the push default at mentions-only will save a lot explicit_content_filter: 0, features: [], + primary_category_id: 0, id: guild_id, max_members: 250000, max_presences: 250000, diff --git a/util/src/entities/index.ts b/util/src/entities/index.ts index c1f979d4..fc18d422 100644 --- a/util/src/entities/index.ts +++ b/util/src/entities/index.ts @@ -3,6 +3,7 @@ export * from "./Attachment"; export * from "./AuditLog"; export * from "./Ban"; export * from "./BaseClass"; +export * from "./Categories"; export * from "./Channel"; export * from "./Config"; export * from "./ConnectedAccount";