diff options
-rw-r--r-- | api/assets/fosscord-login.css | 1 | ||||
-rw-r--r-- | api/src/routes/discoverable-guilds.ts | 26 | ||||
-rw-r--r-- | api/src/routes/discovery.ts | 23 | ||||
-rw-r--r-- | api/src/routes/guild-recommendations.ts | 8 | ||||
-rw-r--r-- | api/src/routes/guilds/#guild_id/discovery-requirements.ts | 39 | ||||
-rw-r--r-- | api/src/routes/guilds/#guild_id/index.ts | 2 | ||||
-rw-r--r-- | api/src/routes/guilds/#guild_id/members/#member_id/index.ts | 21 | ||||
-rw-r--r-- | api/src/routes/partners/#guild_id/requirements.ts | 40 | ||||
-rw-r--r-- | api/src/util/handlers/route.ts | 2 | ||||
-rw-r--r-- | util/src/entities/Categories.ts | 32 | ||||
-rw-r--r-- | util/src/entities/Config.ts | 14 | ||||
-rw-r--r-- | util/src/entities/Guild.ts | 26 | ||||
-rw-r--r-- | util/src/entities/User.ts | 9 | ||||
-rw-r--r-- | util/src/entities/index.ts | 1 | ||||
-rw-r--r-- | util/src/util/Categories.ts | 1 | ||||
-rw-r--r-- | util/src/util/index.ts | 1 |
16 files changed, 196 insertions, 50 deletions
diff --git a/api/assets/fosscord-login.css b/api/assets/fosscord-login.css index 34cf542b..d507c545 100644 --- a/api/assets/fosscord-login.css +++ b/api/assets/fosscord-login.css @@ -26,7 +26,6 @@ h3.title-jXR8lp.marginBottom8-AtZOdT.base-1x0h_U.size24-RIRrxO::after { width: 130px; height: 23px; background-size: contain; - border-radius: 50%; } /* replace TOS text */ diff --git a/api/src/routes/discoverable-guilds.ts b/api/src/routes/discoverable-guilds.ts index 1cf56f84..df4448df 100644 --- a/api/src/routes/discoverable-guilds.ts +++ b/api/src/routes/discoverable-guilds.ts @@ -6,15 +6,29 @@ import { route } from "@fosscord/api"; const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { - const { limit } = req.params; - var showAllGuilds = Config.get().guild.showAllGuildsInDiscovery; + const { offset, limit, categories } = req.query; + var showAllGuilds = Config.get().guild.discovery.showAllGuilds; + var configLimit = Config.get().guild.discovery.limit; // ! 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; + if (categories == undefined) { + guilds = showAllGuilds + ? await Guild.find({ take: Math.abs(Number(limit || configLimit)) }) + : await Guild.find({ where: `"features" LIKE '%DISCOVERABLE%'`, take: Math.abs(Number(limit || configLimit)) }); + total = guilds.length; + } else { + guilds = showAllGuilds + ? await Guild.find({ where: `"primary_category_id" = ${categories}`, take: Math.abs(Number(limit || configLimit)) }) + : await Guild.find({ + where: `"primary_category_id" = ${categories} AND "features" LIKE '%DISCOVERABLE%'`, + take: Math.abs(Number(limit || configLimit)) + }); + total = guilds.length; + } + res.send({ total: total, guilds: guilds, offset: Number(offset || Config.get().guild.discovery.offset), limit: Number(limit || configLimit) }); }); export default router; diff --git a/api/src/routes/discovery.ts b/api/src/routes/discovery.ts index bc495d42..b6a25a13 100644 --- a/api/src/routes/discovery.ts +++ b/api/src/routes/discovery.ts @@ -5,8 +5,27 @@ const router = Router(); router.get("/categories", route({}), (req: Request, res: Response) => { // TODO: - //const { locale, primary_only } = req.query; - res.json([]).status(200); + // Load categories from db instead of hardcoding + + const { locale, primary_only } = req.query; + + let categories; + + 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.send(out); }); export default router; diff --git a/api/src/routes/guild-recommendations.ts b/api/src/routes/guild-recommendations.ts index 503b19b7..3e5b8f32 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; - var showAllGuilds = Config.get().guild.showAllGuildsInDiscovery; + const { limit, personalization_disabled } = req.query; + var showAllGuilds = Config.get().guild.discovery.showAllGuilds; // ! 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 '%DISCOVERABLE%'`, take: Math.abs(Number(limit || 24)) }); res.send({ recommended_guilds: guilds }); }); diff --git a/api/src/routes/guilds/#guild_id/discovery-requirements.ts b/api/src/routes/guilds/#guild_id/discovery-requirements.ts new file mode 100644 index 00000000..ad20633f --- /dev/null +++ b/api/src/routes/guilds/#guild_id/discovery-requirements.ts @@ -0,0 +1,39 @@ +import { Guild, Config } from "@fosscord/util"; + +import { Router, Request, Response } from "express"; +import { route } from "@fosscord/api"; + +const router = Router(); + +router.get("/", route({}), async (req: Request, res: Response) => { + const { guild_id } = req.params; + // TODO: + // Load from database + // Admin control, but for now it allows anyone to be discoverable + + res.send({ + guild_id: guild_id, + safe_environment: true, + healthy: true, + health_score_pending: false, + size: true, + nsfw_properties: {}, + protected: true, + sufficient: true, + sufficient_without_grace_period: true, + valid_rules_channel: true, + retention_healthy: true, + engagement_healthy: true, + age: true, + minimum_age: 0, + health_score: { + avg_nonnew_participators: 0, + avg_nonnew_communicators: 0, + num_intentful_joiners: 0, + perc_ret_w1_intentful: 0 + }, + minimum_size: 0 + }); +}); + +export default router; diff --git a/api/src/routes/guilds/#guild_id/index.ts b/api/src/routes/guilds/#guild_id/index.ts index d8ee86ff..991c3f93 100644 --- a/api/src/routes/guilds/#guild_id/index.ts +++ b/api/src/routes/guilds/#guild_id/index.ts @@ -34,7 +34,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { // @ts-ignore guild.joined_at = member?.joined_at; - return res.json(guild); + return res.send(guild); }); router.patch("/", route({ body: "GuildUpdateSchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/index.ts b/api/src/routes/guilds/#guild_id/members/#member_id/index.ts index ab489743..18a6ed4b 100644 --- a/api/src/routes/guilds/#guild_id/members/#member_id/index.ts +++ b/api/src/routes/guilds/#guild_id/members/#member_id/index.ts @@ -1,5 +1,5 @@ import { Request, Response, Router } from "express"; -import { Member, getPermission, Role, GuildMemberUpdateEvent, emitEvent } from "@fosscord/util"; +import { Member, getPermission, Role, GuildMemberUpdateEvent, emitEvent, Sticker, Emoji, Guild } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { route } from "@fosscord/api"; @@ -43,13 +43,26 @@ router.patch("/", route({ body: "MemberChangeSchema" }), async (req: Request, re }); router.put("/", route({}), async (req: Request, res: Response) => { + + // TODO: Lurker mode + let { guild_id, member_id } = req.params; if (member_id === "@me") member_id = req.user_id; - throw new HTTPError("Maintenance: Currently you can't add a member", 403); - // TODO: only for oauth2 applications + var guild = await Guild.findOneOrFail({ + where: { id: guild_id } }); + + var emoji = await Emoji.find({ + where: { guild_id: guild_id } }); + + var roles = await Role.find({ + where: { guild_id: guild_id } }); + + var stickers = await Sticker.find({ + where: { guild_id: guild_id } }); + + res.send({...guild, emojis: emoji, roles: roles, stickers: stickers}); await Member.addToGuild(member_id, guild_id); - res.sendStatus(204); }); router.delete("/", route({ permission: "KICK_MEMBERS" }), async (req: Request, res: Response) => { diff --git a/api/src/routes/partners/#guild_id/requirements.ts b/api/src/routes/partners/#guild_id/requirements.ts new file mode 100644 index 00000000..545c5c78 --- /dev/null +++ b/api/src/routes/partners/#guild_id/requirements.ts @@ -0,0 +1,40 @@ + +import { Guild, Config } from "@fosscord/util"; + +import { Router, Request, Response } from "express"; +import { route } from "@fosscord/api"; + +const router = Router(); + +router.get("/", route({}), async (req: Request, res: Response) => { + const { guild_id } = req.params; + // TODO: + // Load from database + // Admin control, but for now it allows anyone to be discoverable + + res.send({ + guild_id: guild_id, + safe_environment: true, + healthy: true, + health_score_pending: false, + size: true, + nsfw_properties: {}, + protected: true, + sufficient: true, + sufficient_without_grace_period: true, + valid_rules_channel: true, + retention_healthy: true, + engagement_healthy: true, + age: true, + minimum_age: 0, + health_score: { + avg_nonnew_participators: 0, + avg_nonnew_communicators: 0, + num_intentful_joiners: 0, + perc_ret_w1_intentful: 0 + }, + minimum_size: 0 + }); +}); + +export default router; diff --git a/api/src/util/handlers/route.ts b/api/src/util/handlers/route.ts index 05658ad3..0048c4dd 100644 --- a/api/src/util/handlers/route.ts +++ b/api/src/util/handlers/route.ts @@ -73,7 +73,7 @@ const normalizeBody = (body: any = {}) => { } else { for (const [key, value] of Object.entries(object)) { if (value == null) { - if (key === "icon" || key === "avatar" || key === "banner" || key === "splash") continue; + if (key === "icon" || key === "avatar" || key === "banner" || key === "splash" || key === "discovery_splash") continue; delete object[key]; } else if (typeof value === "object") { normalizeObject(value); diff --git a/util/src/entities/Categories.ts b/util/src/entities/Categories.ts new file mode 100644 index 00000000..1d272118 --- /dev/null +++ b/util/src/entities/Categories.ts @@ -0,0 +1,32 @@ +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 CategoryEntity extends BaseClassWithoutId { // Not using snowflake + + @PrimaryColumn() + id: number; + + @Column() + default: string; + + @Column({ type: "simple-json", nullable: false }) + localizations: string; + + @Column() + is_primary: boolean; + +} \ No newline at end of file diff --git a/util/src/entities/Config.ts b/util/src/entities/Config.ts index 6993cc09..f4a266dc 100644 --- a/util/src/entities/Config.ts +++ b/util/src/entities/Config.ts @@ -157,7 +157,12 @@ export interface ConfigValue { available: Region[]; }; guild: { - showAllGuildsInDiscovery: boolean; + discovery: { + showAllGuilds: boolean; + useRecommendation: boolean; // TODO: Recommendation, privacy concern? + offset: number; + limit: number; + }; autoJoin: { enabled: boolean; guilds: string[]; @@ -353,7 +358,12 @@ export const DefaultConfigOptions: ConfigValue = { ], }, guild: { - showAllGuildsInDiscovery: false, + discovery: { + showAllGuilds: false, + useRecommendation: false, + offset: 0, + limit: 24, + }, autoJoin: { enabled: true, canLeave: true, diff --git a/util/src/entities/Guild.ts b/util/src/entities/Guild.ts index 6a1df4d6..18fa7a0a 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", @@ -108,6 +86,9 @@ export class Guild extends BaseClass { //TODO: https://discord.com/developers/docs/resources/guild#guild-object-guild-features @Column({ nullable: true }) + primary_category_id: number; + + @Column({ nullable: true }) icon?: string; @Column({ nullable: true }) @@ -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: null, id: guild_id, max_members: 250000, max_presences: 250000, diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts index 5f2618e0..1027331a 100644 --- a/util/src/entities/User.ts +++ b/util/src/entities/User.ts @@ -289,12 +289,7 @@ export const defaultSettings: UserSettings = { animate_stickers: 0, contact_sync_enabled: false, convert_emoticons: false, - custom_status: { - emoji_id: undefined, - emoji_name: undefined, - expires_at: undefined, - text: undefined, - }, + custom_status: null, default_guilds_restricted: false, detect_platform_accounts: true, developer_mode: false, @@ -334,7 +329,7 @@ export interface UserSettings { emoji_name?: string; expires_at?: number; text?: string; - }; + } | null; default_guilds_restricted: boolean; detect_platform_accounts: boolean; developer_mode: boolean; 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"; diff --git a/util/src/util/Categories.ts b/util/src/util/Categories.ts new file mode 100644 index 00000000..a3c69da7 --- /dev/null +++ b/util/src/util/Categories.ts @@ -0,0 +1 @@ +//TODO: populate default discord categories + init, get and set methods \ No newline at end of file diff --git a/util/src/util/index.ts b/util/src/util/index.ts index 98e1146c..f7a273cb 100644 --- a/util/src/util/index.ts +++ b/util/src/util/index.ts @@ -1,6 +1,7 @@ export * from "./ApiError"; export * from "./BitField"; export * from "./Token"; +//export * from "./Categories"; export * from "./cdn"; export * from "./Config"; export * from "./Constants"; |