1 module dcord.types.guild; 2 3 import std.stdio, 4 std.algorithm, 5 std.array, 6 std.conv; 7 8 import dcord.types, 9 dcord.client, 10 dcord.gateway; 11 12 alias GuildMap = ModelMap!(Snowflake, Guild); 13 alias RoleMap = ModelMap!(Snowflake, Role); 14 alias GuildMemberMap = ModelMap!(Snowflake, GuildMember); 15 alias EmojiMap = ModelMap!(Snowflake, Emoji); 16 17 /// Enumeration representing the verification level of the guild 18 enum VerificationLevel: ushort { 19 NONE = 0, 20 LOW = 1, 21 MEDIUM = 2, 22 HIGH = 3, 23 EXTREME = 4, 24 } 25 26 /// A class representing roles 27 class Role: IModel { 28 mixin Model; 29 30 Snowflake id; 31 Snowflake guildID; 32 33 string name; 34 bool hoist; 35 bool managed; 36 uint color; 37 Permission permissions; 38 short position; 39 bool mentionable; 40 41 @property Guild guild() { 42 return this.client.state.guilds.get(this.guildID); 43 } 44 } 45 46 class Emoji: IModel { 47 mixin Model; 48 49 Snowflake id; 50 Snowflake guildID; 51 string name; 52 bool requireColons; 53 bool managed; 54 55 Snowflake[] roles; 56 57 @property Guild guild() { 58 return this.client.state.guilds.get(this.guildID); 59 } 60 61 bool matches(string usage) { 62 if (this.name == ":" ~ usage ~ ":") { 63 return true; 64 } else if (this.requireColons) { 65 return false; 66 } else { 67 return this.name == usage; 68 } 69 } 70 } 71 72 class GuildMember : IModel { 73 mixin Model; 74 75 User user; 76 Snowflake guildID; 77 string nick; 78 string joinedAt; 79 bool mute; 80 bool deaf; 81 82 Snowflake[] roles; 83 84 @property Snowflake id() { 85 return this.user.id; 86 } 87 88 @property Guild guild() { 89 return this.client.state.guilds.get(this.guildID); 90 } 91 92 override string toString() { 93 return format("<GuildMember %s#%s (%s / %s)>", 94 this.user.username, 95 this.user.discriminator, 96 this.id, 97 this.guild.id); 98 } 99 100 bool hasRole(Role role) { 101 return this.hasRole(role.id); 102 } 103 104 bool hasRole(Snowflake id) { 105 return this.roles.canFind(id); 106 } 107 } 108 109 class Guild : IModel, IPermissible { 110 mixin Model; 111 mixin Permissible; 112 113 Snowflake id; 114 Snowflake ownerID; 115 Snowflake afkChannelID; 116 Snowflake embedChannelID; 117 string name; 118 string icon; 119 string splash; 120 string region; 121 uint afkTimeout; 122 bool embedEnabled; 123 ushort verificationLevel; 124 ushort mfaLevel; 125 string[] features; 126 127 bool unavailable; 128 129 @JSONListToMap("id") 130 GuildMemberMap members; 131 132 @JSONListToMap("sessionID") 133 VoiceStateMap voiceStates; 134 135 @JSONListToMap("id") 136 ChannelMap channels; 137 138 @JSONListToMap("id") 139 RoleMap roles; 140 141 @JSONListToMap("id") 142 EmojiMap emojis; 143 144 override void initialize() { 145 // It's possible these are not created 146 if (!this.members) return; 147 148 this.members.each((m) { m.guildID = this.id; }); 149 this.voiceStates.each((vc) { vc.guildID = this.id; }); 150 this.channels.each((c) { c.guildID = this.id; }); 151 this.roles.each((r) { r.guildID = this.id; }); 152 this.emojis.each((e) { e.guildID = this.id; }); 153 } 154 155 override string toString() { 156 return format("<Guild %s (%s)>", this.name, this.id); 157 } 158 159 /// Returns a URL to the guild icon 160 string getIconURL(string fmt = "webp", size_t size = 1024) { 161 if (this.icon == "") { 162 return ""; 163 } 164 return format("https://cdn.discordapp.com/icons/%s/%s.%s?size=%s", this.id, this.icon, fmt, size); 165 } 166 167 /// Returns a GuildMember for a given user object 168 GuildMember getMember(User obj) { 169 return this.getMember(obj.id); 170 } 171 172 /// Returns a GuildMember for a given user/member id 173 GuildMember getMember(Snowflake id) { 174 return this.members.get(id); 175 } 176 177 /// Kick a given GuildMember 178 void kick(GuildMember member) { 179 this.kick(member.user); 180 } 181 182 /// Kick a given User 183 void kick(User user) { 184 this.client.api.guildsMembersKick(this.id, user.id); 185 } 186 187 /// Ban a given GuildMember 188 void ban(GuildMember member) { 189 this.ban(member.user); 190 } 191 192 /// Ban a given User 193 void ban(User user) { 194 this.client.api.guildMembersBan(this.id, user.id); 195 } 196 197 /// Unban a given GuildMember 198 void removeBan(GuildMember member) { 199 this.removeBan(member.user); 200 } 201 202 /// Unban a given User 203 void removeBan(User user) { 204 this.client.api.guildMembersRemoveBan(this.id, user.id); 205 } 206 207 /// Default role for this Guild 208 @property Role defaultRole() { 209 return this.roles.pick((r) { 210 return r.id == this.id; 211 }); 212 } 213 214 /// Default channel for this Guild 215 @property Channel defaultChannel() { 216 return this.channels.pick((c) { 217 return c.id == this.id; 218 }); 219 } 220 221 /// Request offline members for this guild 222 void requestOfflineMembers() { 223 this.client.gw.send(new RequestGuildMembers(this.id)); 224 } 225 226 override Permission getPermissions(Snowflake user) { 227 // If the user is the owner, they have all permisisons 228 if(this.ownerID == user)return Permissions.ADMINISTRATOR; 229 230 231 // Otherwise grab the member object 232 GuildMember member = this.getMember(user); 233 Permission perm; 234 auto roles = member.roles.map!(rid => this.roles.get(rid)); 235 236 // Iterate over roles and add permissions 237 foreach (role; roles) { 238 perm |= role.permissions; 239 } 240 241 return perm; 242 } 243 244 /// Set this servers name 245 void setName(string name) { 246 this.client.api.guildsModify(this.id, VibeJSON(["name" : VibeJSON(name)])); 247 } 248 249 /// Set this servers region 250 void setRegion(string region) { 251 this.client.api.guildsModify(this.id, VibeJSON(["region" : VibeJSON(region)])); 252 } 253 }