feat(api): Add requested_by to relationships

This commit is contained in:
Jesse Wierzbinski 2024-06-11 12:32:38 -10:00
parent ffcf01e3cd
commit 20d1a5f39e
No known key found for this signature in database
4 changed files with 95 additions and 51 deletions

View file

@ -4,7 +4,9 @@ import { Relationships } from "~/drizzle/schema";
import type { User } from "~/packages/database-interface/user";
import type { Relationship as APIRelationship } from "~/types/mastodon/relationship";
export type Relationship = InferSelectModel<typeof Relationships>;
export type Relationship = InferSelectModel<typeof Relationships> & {
requestedBy: boolean;
};
/**
* Creates a new relationship between two users.
@ -16,29 +18,32 @@ export const createNewRelationship = async (
owner: User,
other: User,
): Promise<Relationship> => {
return (
await db
.insert(Relationships)
.values({
ownerId: owner.id,
subjectId: other.id,
languages: [],
following: false,
showingReblogs: false,
notifying: false,
followedBy: false,
blocking: false,
blockedBy: false,
muting: false,
mutingNotifications: false,
requested: false,
domainBlocking: false,
endorsed: false,
note: "",
updatedAt: new Date().toISOString(),
})
.returning()
)[0];
return {
...(
await db
.insert(Relationships)
.values({
ownerId: owner.id,
subjectId: other.id,
languages: [],
following: false,
showingReblogs: false,
notifying: false,
followedBy: false,
blocking: false,
blockedBy: false,
muting: false,
mutingNotifications: false,
requested: false,
domainBlocking: false,
endorsed: false,
note: "",
updatedAt: new Date().toISOString(),
})
.returning()
)[0],
requestedBy: false,
};
};
export const checkForBidirectionalRelationships = async (
@ -81,6 +86,7 @@ export const relationshipToAPI = (rel: Relationship): APIRelationship => {
muting_notifications: rel.mutingNotifications,
notifying: rel.notifying,
requested: rel.requested,
requested_by: rel.requestedBy,
showing_reblogs: rel.showingReblogs,
note: rel.note,
};

View file

@ -17,7 +17,7 @@ import { LogLevel } from "~/packages/log-manager";
import type { Application } from "./Application";
import type { EmojiWithInstance } from "./Emoji";
import { objectToInboxRequest } from "./Federation";
import { createNewRelationship } from "./Relationship";
import { type Relationship, createNewRelationship } from "./Relationship";
import type { Token } from "./Token";
export type UserType = InferSelectModel<typeof Users>;
@ -121,22 +121,33 @@ export const followRequestUser = async (
reblogs = false,
notify = false,
languages: string[] = [],
): Promise<InferSelectModel<typeof Relationships>> => {
): Promise<Relationship> => {
const isRemote = followee.isRemote();
const updatedRelationship = (
await db
.update(Relationships)
.set({
following: isRemote ? false : !followee.getUser().isLocked,
requested: isRemote ? true : followee.getUser().isLocked,
showingReblogs: reblogs,
notifying: notify,
languages: languages,
})
.where(eq(Relationships.id, relationshipId))
.returning()
)[0];
await db
.update(Relationships)
.set({
following: isRemote ? false : !followee.getUser().isLocked,
requested: isRemote ? true : followee.getUser().isLocked,
showingReblogs: reblogs,
notifying: notify,
languages: languages,
})
.where(eq(Relationships.id, relationshipId));
const updatedRelationship = await db.query.Relationships.findFirst({
where: (rel, { eq }) => eq(rel.id, relationshipId),
extras: {
requestedBy:
sql<boolean>`(SELECT "requested" FROM "Relationships" WHERE "Relationships"."ownerId" = ${followee.id} AND "Relationships"."subjectId" = ${follower.id})`.as(
"requested_by",
),
},
});
if (!updatedRelationship) {
throw new Error("Failed to update relationship");
}
if (isRemote) {
// Federate
@ -165,16 +176,29 @@ export const followRequestUser = async (
} to ${followee.getUri()}`,
);
return (
await db
.update(Relationships)
.set({
following: false,
requested: false,
})
.where(eq(Relationships.id, relationshipId))
.returning()
)[0];
await db
.update(Relationships)
.set({
following: false,
requested: false,
})
.where(eq(Relationships.id, relationshipId));
const result = await db.query.Relationships.findFirst({
where: (rel, { eq }) => eq(rel.id, relationshipId),
extras: {
requestedBy:
sql<boolean>`(SELECT "requested" FROM "Relationships" WHERE "Relationships"."ownerId" = ${followee.id} AND "Relationships"."subjectId" = ${follower.id})`.as(
"requested_by",
),
},
});
if (!result) {
throw new Error("Failed to update relationship");
}
return result;
}
} else {
await db.insert(Notifications).values({
@ -458,13 +482,19 @@ export const retrieveToken = async (
export const getRelationshipToOtherUser = async (
user: User,
other: User,
): Promise<InferSelectModel<typeof Relationships>> => {
): Promise<Relationship> => {
const foundRelationship = await db.query.Relationships.findFirst({
where: (relationship, { and, eq }) =>
and(
eq(relationship.ownerId, user.id),
eq(relationship.subjectId, other.id),
),
extras: {
requestedBy:
sql<boolean>`(SELECT "requested" FROM "Relationships" WHERE "Relationships"."ownerId" = ${other.id} AND "Relationships"."subjectId" = ${user.id})`.as(
"requested_by",
),
},
});
if (!foundRelationship) {

View file

@ -1,6 +1,7 @@
import { applyConfig, auth, handleZodError, qsQuery } from "@/api";
import { errorResponse, jsonResponse } from "@/response";
import { zValidator } from "@hono/zod-validator";
import { sql } from "drizzle-orm";
import type { Hono } from "hono";
import { z } from "zod";
import {
@ -8,7 +9,7 @@ import {
relationshipToAPI,
} from "~/database/entities/Relationship";
import { db } from "~/drizzle/db";
import { RolePermissions } from "~/drizzle/schema";
import { Relationships, RolePermissions } from "~/drizzle/schema";
import { User } from "~/packages/database-interface/user";
export const meta = applyConfig({
@ -54,6 +55,12 @@ export default (app: Hono) =>
inArray(relationship.subjectId, ids),
eq(relationship.ownerId, self.id),
),
extras: {
requestedBy:
sql<boolean>`(SELECT "requested" FROM "Relationships" WHERE "Relationships"."ownerId" = ${Relationships.id} AND "Relationships"."subjectId" = ${self.id})`.as(
"requested_by",
),
},
});
const missingIds = ids.filter(

View file

@ -7,6 +7,7 @@ export type Relationship = {
muting: boolean;
muting_notifications: boolean;
requested: boolean;
requested_by: boolean;
domain_blocking: boolean;
showing_reblogs: boolean;
endorsed: boolean;