API: Client-side permissions calculator.

This commit is contained in:
Paul
2021-06-10 14:23:33 +01:00
parent 1f3294157a
commit 20043cc18d
3 changed files with 132 additions and 5 deletions
+125
View File
@@ -0,0 +1,125 @@
import { Client } from '../Client';
import { Users } from './objects';
export const UserPermission = {
Access: 0b00000000000000000000000000000001, // 1
ViewProfile: 0b00000000000000000000000000000010, // 2
SendMessage: 0b00000000000000000000000000000100, // 4
Invite: 0b00000000000000000000000000001000, // 8
}
export const ChannelPermission = {
View: 0b00000000000000000000000000000001, // 1
SendMessage: 0b00000000000000000000000000000010, // 2
ManageMessages: 0b00000000000000000000000000000100, // 4
ManageChannel: 0b00000000000000000000000000001000, // 8
VoiceCall: 0b00000000000000000000000000010000, // 16
InviteOthers: 0b00000000000000000000000000100000, // 32
}
export const ServerPermission = {
View: 0b00000000000000000000000000000001, // 1
ManageMembers: 0b00000000000000000000000000000010, // 2
ManageChannels: 0b00000000000000000000000000000100, // 4
ManageServer: 0b00000000000000000000000000001000, // 8
KickMembers: 0b00000000000000000000000000010000, // 16
BanMembers: 0b00000000000000000000000000100000, // 32
ChangeNickname: 0b00000000000000000001000000000000, // 4096
ManageNicknames: 0b00000000000000000010000000000000, // 8192
ChangeAvatar: 0b00000000000000000100000000000000, // 16392
RemoveAvatars: 0b00000000000000001000000000000000, // 32784
}
const U32_MAX = 2**32 - 1; // 4294967295
class PermissionCalculator {
client: Client;
constructor(client: Client) {
this.client = client;
}
forUser(user_id: string): number {
let user = this.client.users.get(user_id);
if (typeof user === 'undefined') return 0;
let permissions = 0;
switch (user.relationship) {
case Users.Relationship.Friend:
case Users.Relationship.User:
return U32_MAX;
case Users.Relationship.Blocked:
case Users.Relationship.BlockedOther:
return UserPermission.Access;
case Users.Relationship.Incoming:
case Users.Relationship.Outgoing:
permissions = UserPermission.Access;
}
if (this.client.channels.toArray().find(channel =>
(channel.channel_type === 'Group' || channel.channel_type === 'DirectMessage')
&& channel.recipients.includes(user_id)
)) {
permissions |= UserPermission.Access | UserPermission.ViewProfile;
}
return permissions;
}
forChannel(channel_id: string): number {
let channel = this.client.channels.get(channel_id);
if (typeof channel === 'undefined') return 0;
// This takes assumptions in the fact that
// by having the channel in the channel map,
// we are part of the channel, hence have
// access to it.
switch (channel.channel_type) {
case 'SavedMessages': return U32_MAX;
case 'DirectMessage': {
let recipient = this.client.channels.getRecipient(channel_id);
let user_permissions = this.forUser(recipient);
if (user_permissions & UserPermission.SendMessage) {
return ChannelPermission.View
+ ChannelPermission.SendMessage
+ ChannelPermission.VoiceCall;
} else {
return 0;
}
}
case 'Group': return ChannelPermission.View
+ ChannelPermission.SendMessage
+ ChannelPermission.ManageChannel
+ ChannelPermission.VoiceCall
+ ChannelPermission.InviteOthers;
case 'TextChannel': {
let server = this.client.servers.get(channel.server);
if (typeof server === 'undefined') return 0;
if (server.owner === this.client.user?._id) {
return U32_MAX;
} else {
return ChannelPermission.View
+ ChannelPermission.SendMessage
+ ChannelPermission.InviteOthers;
}
}
}
}
forServer(server_id: string): number {
let server = this.client.servers.get(server_id);
if (typeof server === 'undefined') return 0;
if (server.owner === this.client.user?._id) {
return U32_MAX;
} else {
return ServerPermission.View
+ ServerPermission.ChangeNickname
+ ServerPermission.ChangeAvatar;
}
}
}
+3 -3
View File
@@ -155,10 +155,10 @@ export default class Servers extends Collection<Server> {
/**
* Get the banner URL of a server
* @param id ID of the target server
* @param size Size to resize image to
* @param width Width to resize image to
* @param allowAnimation Whether to allow links to the original GIFs to be returned
*/
getBannerURL(id: string, size?: number, allowAnimation?: boolean) {
getBannerURL(id: string, width?: number, allowAnimation?: boolean) {
let url = this.client.configuration?.features.autumn.url;
let server = this.getMutable(id);
if (server?.banner) {
@@ -166,7 +166,7 @@ export default class Servers extends Collection<Server> {
if (allowAnimation && server.banner.content_type === 'image/gif') {
return baseURL;
} else {
return baseURL + (size ? `?size=${size}` : '');
return baseURL + (width ? `?width=${width}` : '');
}
}
}
+4 -2
View File
@@ -136,8 +136,10 @@ export default class Users extends Collection<User> {
* Get the avatar URL of a user
* @param id ID of the target user
* @param size Size to resize image to
* @param allowAnimation Whether to allow GIFs to play
* @param disableFallback Don't return default avatar if no avatar
*/
getAvatarURL(id: string, size?: number, allowAnimation?: boolean) {
getAvatarURL(id: string, size?: number, allowAnimation?: boolean, disableFallback?: boolean) {
let url = this.client.configuration?.features.autumn.url;
let attachment = this.getMutable(id)?.avatar;
if (url && attachment) {
@@ -147,7 +149,7 @@ export default class Users extends Collection<User> {
} else {
return baseURL + (size ? `?size=${size}` : '');
}
} else {
} else if (!disableFallback) {
return this.getDefaultAvatarURL(id);
}
}