Finished implementing NetworkService

This commit is contained in:
2026-04-02 17:26:23 +02:00
parent bf4bd3e218
commit f61fcb4daa
13 changed files with 1304 additions and 37 deletions

View File

@@ -1,25 +1,12 @@
import axios, { AxiosInstance } from 'axios';
import axios, {AxiosInstance} from 'axios';
import {environment} from "./environment";
let client: AxiosInstance;
export const getClient = () => {
if (!client) {
const env = environment.get();
const env = environment.get();
client = axios.create({
baseURL: env.apiUrl,
timeout: 1000,
headers: { 'Content-Type': 'application/json' }
});
/*client.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});*/
}
return client;
return axios.create({
baseURL: env.apiUrl,
timeout: 5000,
headers: {'Content-Type': 'application/json'}
});
};

View File

@@ -7,4 +7,11 @@ export interface RGB {
export interface TimeStamp {
T: number;
I: number;
}
export interface PublicUserData {
pfp: string
displayName: string
username: string
userid: string
}

View File

@@ -1,5 +1,5 @@
// Request schemas
import {RGB, TimeStamp} from "./common.schema";
import {PublicUserData, RGB, TimeStamp} from "./common.schema";
export interface GetInvitesReq {
networkId: string
@@ -166,6 +166,13 @@ export interface EditRankReq {
rankId: string
}
export interface DeleteChannelReq {
userid: string
categoryId: string
networkId: string
channelId: string
}
export interface DeleteRankReq {
userid: string
networkId: string
@@ -195,7 +202,7 @@ export interface AssignRankToMemberReq {
networkId: string
}
export interface GetMemberReq {
export interface GetMembersReq {
userid: string
networkId: string
}
@@ -350,6 +357,14 @@ export interface NetworkDiscovery {
networkId: string
}
export interface DetailedMemberList {
rankId: string
name: string
color: RGB
icon: string
members: PublicUserData[]
}
// WebSocket payloads
export interface WSCategoryDeletedPayload {
categoryId: string
@@ -448,4 +463,29 @@ export interface WSNewNamePayload {
export interface WSNewChannelPayload {
in: string
channel: NetworkChannel
}
// Constants
export const NetworkPermissions = {
createAndEditCategories: 2,
deleteCategories: 4,
createAndEditChannels: 8,
deleteChannels: 16,
deleteAnyMessage: 32,
pinMessages: 64,
createAndEditRanks: 128,
deleteRanks: 256,
changeNetworkNamePictureAndVisibility: 512,
createEmojis: 1024,
deleteEmojis: 2048,
manageEmbed: 4096,
createWebhooks: 8192,
deleteWebhooks: 16384,
createInvites: 32768,
deleteInvites: 65536,
sendMessages: 131072,
seeChannels: 262144,
banMembers: 524288,
kickMembers: 1048576,
unAndAssignRanksToMember: 2097152,
}

View File

@@ -8,7 +8,7 @@ import {
} from "../../domain/authService.schema";
import {GenericSuccessBody} from "../../domain/http.schema";
export const authHandlers = [
export const networkHandlers = [
http.get('*/user/authOptions', () => {
return HttpResponse.json(<AuthMethods>{
email: true,

View File

@@ -0,0 +1,74 @@
import {http, HttpResponse} from "msw";
import {
CreateCategoryReq, CreateInviteReq,
CreateNetworkReq, DetailedMemberList,
Network,
NetworkCategory,
NetworkInvite, POW
} from "../../domain/networkService.schema";
import {PublicUserData} from "../../domain/common.schema";
export const authHandlers = [
http.get('*/network/invites', () => {
return HttpResponse.json(<NetworkInvite[]>[
{
inviteId: "inviteId"
}
])
}),
http.post('*/network/create', async ({request}) => {
const body = await request.json() as CreateNetworkReq
return HttpResponse.json(<Network>{
name: body.name,
visibility: body.visibility
})
}),
http.post('*/network/get', async () => {
return HttpResponse.json(<Network[]>[{
name: "Test network"
}])
}),
http.post('*/network/createCategory', async ({request}) => {
const body = await request.json() as CreateCategoryReq
return HttpResponse.json(<NetworkCategory>{
name: body.name,
desc: body.description
})
}),
http.post('*/network/createInvite', async ({request}) => {
const body = await request.json() as CreateInviteReq
return HttpResponse.json(<NetworkInvite>{
onetime: body.times == "once"
})
}),
http.patch('*/network/getOverwrites', async ({request}) => {
return HttpResponse.json(<POW[]>[{
permissionNumber: 5000
}])
}),
http.patch('*/network/getChannelOverwrites', async ({request}) => {
return HttpResponse.json(<POW[]>[{
permissionNumber: 5000
}])
}),
http.patch('*/network/getBannedMembers', async ({request}) => {
return HttpResponse.json(<PublicUserData[]>[{
username: "bob",
displayName: "Bob",
}])
}),
http.patch('*/network/getMembers', async ({request}) => {
return HttpResponse.json(<DetailedMemberList[]>[{
name: "Test rank",
members: [{displayName: "Bob"}]
}])
}),
]

View File

@@ -1,5 +1,7 @@
import {authHandlers} from "./handlers/auth.http";
import {networkHandlers} from "./handlers/auth.http";
import {authHandlers} from "./handlers/network.http";
export const allHandlers = [
...authHandlers
...authHandlers,
...networkHandlers
]

View File

@@ -0,0 +1,21 @@
import {DatabaseAPI} from "../../storage/database";
export class DatabaseMock implements DatabaseAPI {
database: { [collection: string]: { [key: string]: string } } = {};
set(collection: string, key: string, value: any) {
this.database[collection][key] = JSON.stringify(value);
}
get(collection: string, key: string): any {
return this.database[collection][key]
}
delete(collection: string, key: string) {
delete this.database[collection][key];
}
flush() {
this.database = {};
}
}

View File

@@ -4,8 +4,9 @@ import {VerificationTypeEmail} from "../domain/authService.schema";
import {faker} from "@faker-js/faker/locale/en";
describe("AuthService", () => {
const service = new AuthService();
it("should return authMethods", async () => {
const service = new AuthService();
const methods = await service.getAuthMethods("")
expect(methods.sms).toBeFalsy()
expect(methods.email).toBeTruthy()
@@ -13,57 +14,47 @@ describe("AuthService", () => {
})
it("should send OTP code", async () => {
const service = new AuthService();
const code = await service.otpSendCode("bob@example.com", VerificationTypeEmail)
expect(code).toBe(5000)
})
it("should send password reset code", async () => {
const service = new AuthService();
const code = await service.resetPassword("bob@example.com")
expect(code).toBe(5000)
})
it("should send PLE code", async () => {
const service = new AuthService();
const code = await service.pleSendVCode("bob@example.com", VerificationTypeEmail)
expect(code).toBe(5000)
})
it("should throw on wrong OTP code", async () => {
const service = new AuthService();
await expect(service.otpVerifyCode("bob@example.com", VerificationTypeEmail, 9999)).rejects.toThrow()
})
it("should throw on wrong password reset code", async () => {
const service = new AuthService();
await expect(service.verifyPasswordReset("bob@example.com", 9999, "newPassword")).rejects.toThrow()
})
it("should throw on wrong PLE code", async () => {
const service = new AuthService();
await expect(service.pleVerifyCode("bob@example.com", VerificationTypeEmail, 9999)).rejects.toThrow()
})
it("should throw on wrong password", async () => {
const service = new AuthService();
await expect(service.loginPasswordAuth("bob@example.com", "wrongPasswd")).rejects.toThrow();
})
it("should detect taken username", async () => {
const service = new AuthService();
const taken = await service.isUsernameUsed("username")
expect(taken).toBeTruthy()
})
it("should detect taken e-mail address", async () => {
const service = new AuthService();
const taken = await service.isEmailUsed("taken@example.com")
expect(taken).toBeTruthy()
})
it("should register passwordless account", async () => {
const service = new AuthService();
const username = faker.internet.username()
const displayName = faker.internet.displayName()
const userData = await service.finishPLEAccount(

View File

@@ -164,6 +164,7 @@ export class AuthService {
});
return resp.data.authCode
} catch (e) {
console.log(e)
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}

View File

@@ -0,0 +1,66 @@
import {describe, expect, it} from "vitest";
import {NetworkService} from "./networkService";
import {DatabaseMock} from "../mocks/storage/database";
import {faker} from "@faker-js/faker/locale/en";
import {getClient} from "../core/http";
import {environment, SDKConfig} from "../core/environment";
describe("NetworkService", () => {
const service = new NetworkService("", "", "", new DatabaseMock(), getClient())
it('should get invites', async () => {
const invites = await service.getInvites();
expect(invites[0].inviteId).toBe("inviteId")
});
it('should create a network', async () => {
const netName = faker.internet.displayName()
const network = await service.create(
netName,
"private",
null
);
expect(network.name).toBe(netName)
expect(network.visibility).toBe("private")
});
it('should create a category', async () => {
const catName = faker.internet.displayName()
const catDesc = faker.lorem.sentence()
const category = await service.createCategory(
catName,
catDesc
);
expect(category.name).toBe(catName)
expect(category.desc).toBe(catDesc)
});
it('should create an invite', async () => {
const invite = await service.createInvite(
"once",
);
expect(invite.onetime).toBeTruthy()
});
it('should get permission overwrites', async () => {
const ow = await service.getOverwrites("", "");
expect(ow[0].permissionNumber).toBe(5000)
});
it('should get channel permission overwrites', async () => {
const ow = await service.getChannelOverwrites("", "", "");
expect(ow[0].permissionNumber).toBe(5000)
});
it('should get banned members', async () => {
const bannedMembers = await service.getBannedMembers();
expect(bannedMembers[0].username).toBe("bob")
expect(bannedMembers[0].displayName).toBe("Bob")
});
it('should get the detailed member list', async () => {
const members = await service.getMembers();
expect(members[0].name).toBe("Test rank")
expect(members[0].members[0].displayName).toBe("Bob")
});
})

View File

@@ -1,4 +1,884 @@
import {DatabaseAPI} from "../storage/database";
import {AuthMethods} from "../domain/authService.schema";
import {getClient} from "../core/http";
import {AxiosInstance, isAxiosError} from "axios";
import {GenericErrorBody} from "../domain/http.schema";
import {
AcceptInviteReq, AssignRankToMemberReq, BanMemberReq, ChangeVisibilityReq, CreateCategoryReq, CreateChannelReq,
CreateInviteReq,
CreateNetworkReq, CreateRankReq, DeleteCategoryReq,
DeleteChannelReq, DeleteNetworkReq, DeleteRankReq,
DetailedMemberList, EditCategoryReq, EditChannelReq, EditNameReq, EditRankReq,
GetBannedMembersReq, GetChannelOverwritesReq, GetMembersReq,
GetNetworksReq, GetOverwritesReq, JoinPublicNetworkReq, JoinWebSocketRoomReq, KickMemberReq, LeaveNetworkReq,
ModifyPermissionsReq, MoveCategoryReq, MoveRankReq,
Network, NetworkCategory, NetworkChannel, NetworkDiscovery,
NetworkInvite, NetworkRank, OverwriteChannelPermissionReq, OverwritePermissionReq, PermissionUpdate, POW,
RemoveRankFromMemberReq, ToggleCategoryMuteReq, ToggleChannelNetworkMuteReq, ToggleNetworkMuteReq,
UnbanMemberReq, UploadNewPictureReq
} from "../domain/networkService.schema";
import {PublicUserData, RGB} from "../domain/common.schema";
import {http} from "msw";
export class NetworkService {
constructor(networkId: string) {
userid: string;
networkId: string;
database: DatabaseAPI;
client: AxiosInstance
constructor(userid: string, token: string, networkId: string, database: DatabaseAPI, httpClientOverwrite: AxiosInstance | null) {
this.userid = userid;
this.networkId = networkId;
this.database = database;
this.client = (httpClientOverwrite ?? getClient()).create({
headers: {
"Authorization": token
}
})
}
/**
* Fetches all invites created for the network
*/
async getInvites(): Promise<NetworkInvite[]> {
try {
const resp = await this.client.get<NetworkInvite[]>(`network/invites?networkId=${this.networkId}&userid=${this.userid}`);
return resp.data
} catch (e) {
console.log(e)
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Creates a new network
* @param name Provided by the user
* @param visibility name Provided by the user
* @param data Optional base-64 encoded image for a custom network picture
*/
async create(name: string, visibility: "public" | "private", data: string | null): Promise<Network> {
try {
const resp = await this.client.post<Network>("network/create", <CreateNetworkReq>{
userid: this.userid,
data: data,
name: name,
visibility: visibility,
isImage: data != null,
monogramLetter: name[0]
});
return resp.data
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Gets all networks the user is in
*/
async get(): Promise<Network[]> {
try {
const resp = await this.client.post<Network[]>("network/get", <GetNetworksReq>{
userid: this.userid,
});
return resp.data
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Accepts the invite and joins the network
* @param inviteId
*/
async acceptInvite(inviteId: string): Promise<void> {
try {
const resp = await this.client.post("network/acceptInvite", <AcceptInviteReq>{
userid: this.userid,
inviteId: inviteId,
});
return
} catch (e) {
console.log(e)
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Joins a public network
* @param networkId
*/
async joinPublicNetwork(networkId: string): Promise<void> {
try {
const resp = await this.client.post("network/joinNetworkDiscovery", <JoinPublicNetworkReq>{
userid: this.userid,
networkId: networkId,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Creates a new category in the network
* @param name Provided by the user
* @param description Provided by the user
*/
async createCategory(name: string, description: string): Promise<NetworkCategory> {
try {
const resp = await this.client.post<NetworkCategory>("network/createCategory", <CreateCategoryReq>{
userid: this.userid,
networkId: this.networkId,
name: name,
description: description
});
return resp.data
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Deletes the selected category
* @param categoryId
*/
async deleteCategory(categoryId: string): Promise<void> {
try {
const resp = await this.client.patch("network/deleteCategory", <DeleteCategoryReq>{
userid: this.userid,
categoryId: categoryId,
networkId: this.networkId,
});
return
} catch (e) {
console.log(e)
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Moves a category from a specific place to another
* @param from The category that will be moved
* @param to The place where to category will be moved to
*/
async moveCategory(from: number, to: number): Promise<void> {
try {
await this.client.patch("network/moveCategory", <MoveCategoryReq>{
userid: this.userid,
networkId: this.networkId,
from: from,
to: to,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Leaves the network
*/
async leave(): Promise<void> {
try {
await this.client.post("network/leave", <LeaveNetworkReq>{
userid: this.userid,
networkId: this.networkId
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Deletes the network (Must be owned by the user)
*/
async delete(): Promise<void> {
try {
await this.client.post("network/delete", <DeleteNetworkReq>{
userid: this.userid,
networkId: this.networkId
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Creates a new rank
* @param name Provided by the user
* @param colors Provided by the user
* @param icon Optionally provided by the user
*/
async createRank(name: string, colors: RGB, icon: string | null): Promise<NetworkRank> {
try {
const resp = await this.client.post<NetworkRank>("network/createRank", <CreateRankReq>{
userid: this.userid,
networkId: this.networkId,
colors: colors,
icon: icon,
name: name,
});
return resp.data
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Creates a new invite
* @param times Whether the invite should be used once or unlimited times
*/
async createInvite(times: "once" | "unlimited"): Promise<NetworkInvite> {
try {
const resp = await this.client.post<NetworkInvite>("network/createInvite", <CreateInviteReq>{
userid: this.userid,
networkId: this.networkId,
times: times,
});
return resp.data
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Moves a rank from a specific place to another
* @param from The rank that will be moved
* @param to The place where to rank will be moved to
*/
async moveRank(from: number, to: number): Promise<void> {
try {
const resp = await this.client.patch("network/moveRank", <MoveRankReq>{
userid: this.userid,
networkId: this.networkId,
from: from,
to: to,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Kicks a specific member
* @param memberId
*/
async kickMember(memberId: string): Promise<void> {
try {
const resp = await this.client.patch("network/kickMember", <KickMemberReq>{
userid: this.userid,
networkId: this.networkId,
memberId: memberId,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Bans a specific member
* @param memberId
*/
async banMember(memberId: string): Promise<void> {
try {
const resp = await this.client.patch("network/banMember", <BanMemberReq>{
userid: this.userid,
networkId: this.networkId,
memberId: memberId,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Modifies the permissions of the selected rank
* @param permissionChanges
* @param rankId
*/
async modifyRankPermissions(permissionChanges: PermissionUpdate[], rankId: string): Promise<void> {
try {
await this.client.patch("network/modifyPermissions", <ModifyPermissionsReq>{
userid: this.userid,
networkId: this.networkId,
permissionChanges: permissionChanges,
rankId: rankId
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Creates a permission overwrite for a category
* @param permissionNumber
* @param to
* @param rankId
* @param categoryId
*/
async overwritePermission(permissionNumber: number, to: string, rankId: string, categoryId: string): Promise<void> {
try {
await this.client.patch("network/overwritePermission", <OverwritePermissionReq>{
userid: this.userid,
networkId: this.networkId,
permissionNumber: permissionNumber,
rankId: rankId,
categoryId: categoryId,
category: categoryId,
to: to,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Creates a permission overwrite for a specific channel
* @param permissionNumber
* @param to
* @param rankId
* @param categoryId
* @param channelId
*/
async overwriteChannelPermission(permissionNumber: number, to: string, rankId: string, categoryId: string, channelId: string): Promise<void> {
try {
await this.client.patch("network/overwriteChannelPermission", <OverwriteChannelPermissionReq>{
userid: this.userid,
networkId: this.networkId,
permissionNumber: permissionNumber,
rankId: rankId,
categoryId: categoryId,
to: to,
channelId: channelId,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Fetches all permission overwrites made for a category
* @param rankId
* @param categoryId
*/
async getOverwrites(rankId: string, categoryId: string): Promise<POW[]> {
try {
const resp = await this.client.patch<POW[]>("network/getOverwrites", <GetOverwritesReq>{
userid: this.userid,
networkId: this.networkId,
rankId: rankId,
categoryId: categoryId,
category: categoryId,
});
return resp.data
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
Fetches all permission overwrites made for a channel
* @param rankId
* @param categoryId
* @param channelId
*/
async getChannelOverwrites(rankId: string, categoryId: string, channelId: string): Promise<POW[]> {
try {
const resp = await this.client.patch<POW[]>("network/getChannelOverwrites", <GetChannelOverwritesReq>{
userid: this.userid,
networkId: this.networkId,
rankId: rankId,
categoryId: categoryId,
category: categoryId,
channelId: channelId
});
return resp.data
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Modifies the name and/or description of a channel
* @param categoryId
* @param name
* @param desc
*/
async editCategory(categoryId: string, name: string, desc: string): Promise<void> {
try {
await this.client.patch("network/editCategory", <EditCategoryReq>{
userid: this.userid,
networkId: this.networkId,
categoryId: categoryId,
name: name,
desc: desc,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Unbans a specific member
* @param memberId
*/
async unbanMember(memberId: string): Promise<void> {
try {
await this.client.patch("network/unbanMember", <UnbanMemberReq>{
userid: this.userid,
networkId: this.networkId,
memberId: memberId,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Gets all banned members public user data
*/
async getBannedMembers(): Promise<PublicUserData[]> {
try {
const resp = await this.client.patch<PublicUserData[]>("network/getBannedMembers", <GetBannedMembersReq>{
userid: this.userid,
networkId: this.networkId
});
return resp.data
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Deletes a specific rank
* @param rankId
*/
async deleteRank(rankId: string): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/deleteRank", <DeleteRankReq>{
userid: this.userid,
networkId: this.networkId,
rankId: rankId,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Modifies the name, colors and/or the icon of a specific rank
* @param rankId
* @param name
* @param colors
* @param icon
*/
async editRank(rankId: string, name: string, colors: RGB, icon: string | null): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/editRank", <EditRankReq>{
userid: this.userid,
networkId: this.networkId,
rankId: rankId,
colors: colors,
icon: icon,
name: name,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Deletes a specific channel
* @param categoryId
* @param channelId
*/
async deleteChannel(categoryId: string, channelId: string): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/deleteChannel", <DeleteChannelReq>{
userid: this.userid,
networkId: this.networkId,
categoryId: categoryId,
channelId: channelId,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Edits a specific channel
* @param categoryId
* @param channelId
* @param name
* @param desc
*/
async editChannel(categoryId: string, channelId: string, name: string, desc: string): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/editChannel", <EditChannelReq>{
userid: this.userid,
networkId: this.networkId,
categoryId: categoryId,
channelId: channelId,
name: name,
desc: desc,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Removes a rank from a specific member
* @param targetUserId
* @param rankId
*/
async removeRankFromMember(targetUserId: string, rankId: string): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/removeRankFromMember", <RemoveRankFromMemberReq>{
userid: this.userid,
networkId: this.networkId,
rankId: rankId,
targetUserId: targetUserId,
userId: this.userid,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Assigns a rank to a specific member
* @param targetUserId
* @param rankId
*/
async assignRankToMember(targetUserId: string, rankId: string): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/assignRankToMember", <AssignRankToMemberReq>{
userid: this.userid,
networkId: this.networkId,
rankId: rankId,
targetUserId: targetUserId,
userId: this.userid,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Gets a detailed member list with all ranks and members inside them
*/
async getMembers(): Promise<DetailedMemberList[]> {
try {
const resp = await this.client.patch<DetailedMemberList[]>("network/getMembers", <GetMembersReq>{
userid: this.userid,
networkId: this.networkId,
});
return resp.data
} catch (e) {
console.error(e)
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Uploads a new network picture
* @param picId
*/
async uploadNewPic(picId: string): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/uploadNewPic", <UploadNewPictureReq>{
userid: this.userid,
networkId: this.networkId,
picId: picId,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Changes the visibility of the network
* @param to
*/
async changeVisibility(to: "public" | "private"): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/changeVisibility", <ChangeVisibilityReq>{
userid: this.userid,
networkId: this.networkId,
to: to,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Edits the name of the network
* @param name
*/
async editName(name: string): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/editName", <EditNameReq>{
userid: this.userid,
networkId: this.networkId,
name: name,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Creates a new channel inside a category in the network
* @param categoryId
* @param type
* @param description
* @param name
*/
async createChannel(categoryId: string, type: "message" | "broadcast" | "voice", description: string, name: string): Promise<NetworkChannel> {
try {
const resp = await this.client.patch<NetworkChannel>("network/createChannel", <CreateChannelReq>{
userid: this.userid,
networkId: this.networkId,
categoryId: categoryId,
name: name,
description: description,
type: type,
});
return resp.data
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* (un)mutes the network
*/
async toggleMute(): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/toggleMute", <ToggleNetworkMuteReq>{
userid: this.userid,
networkId: this.networkId
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* (un)mutes a category inside the network
* @param categoryId
*/
async toggleCategoryMute(categoryId: string): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/toggleCatMute", <ToggleCategoryMuteReq>{
userid: this.userid,
networkId: this.networkId,
categoryId: categoryId,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* (un)mutes a channel inside a category in the network
* @param channelId
*/
async toggleChannelMute(channelId: string): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("network/toggleChanMute", <ToggleChannelNetworkMuteReq>{
userid: this.userid,
networkId: this.networkId,
channelId: channelId,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Starts listening for live changes inside the network
* @param connId
*/
async joinWebSocketRoom(connId: string): Promise<void> {
try {
await this.client.patch<PublicUserData[]>("v2/network/joinWebSocketRoom", <JoinWebSocketRoomReq>{
userid: this.userid,
networkId: this.networkId,
connId: connId,
});
return
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Fetches network data from an invite
* @param inviteId
*/
async getFromInvite(inviteId: string): Promise<Network> {
try {
const resp = await this.client.get<Network>(`network/fromInvite?inviteId=${inviteId}`);
return resp.data
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
/**
* Fetches network discovery (A list of public networks)
*/
async getDiscovery(): Promise<NetworkDiscovery[]> {
try {
const resp = await this.client.get<NetworkDiscovery[]>("network/discovery");
return resp.data
} catch (e) {
if (isAxiosError<GenericErrorBody>(e)) {
throw e;
}
throw new Error("Unexpected error")
}
}
}

6
src/storage/database.ts Normal file
View File

@@ -0,0 +1,6 @@
export interface DatabaseAPI {
set(collection: string, key: string, value: any): void;
get(collection: string, key: string): string;
delete(collection: string, key: string): void;
flush(): void;
}