1 module dscord.types.guild; 2 3 import std.stdio, 4 std.algorithm, 5 std.array, 6 std.conv; 7 8 import dscord.client, 9 dscord.types.all; 10 11 alias GuildMap = ModelMap!(Snowflake, Guild); 12 alias RoleMap = ModelMap!(Snowflake, Role); 13 alias GuildMemberMap = ModelMap!(Snowflake, GuildMember); 14 alias EmojiMap = ModelMap!(Snowflake, Emoji); 15 16 bool memberHasRoleWithin(RoleMap map, GuildMember mem) { 17 foreach (ref role; map.values) { 18 if (mem.hasRole(role)) return true; 19 } 20 return false; 21 } 22 23 class Role : IModel { 24 mixin Model; 25 26 Snowflake id; 27 Guild guild; 28 Permission permissions; 29 30 string name; 31 uint color; 32 bool hoist; 33 short position; 34 bool managed; 35 bool mentionable; 36 37 this(Client client, ref JSON obj) { 38 super(client, obj); 39 } 40 41 this(Guild guild, ref JSON obj) { 42 this.guild = guild; 43 super(guild.client, obj); 44 } 45 46 override void load(ref JSON obj) { 47 obj.keySwitch!( 48 "id", "name", "hoist", "position", "permissions", 49 "managed", "mentionable", "color" 50 )( 51 { this.id = readSnowflake(obj); }, 52 { this.name = obj.read!string; }, 53 { this.hoist = obj.read!bool; }, 54 { this.position = obj.read!short; }, 55 { this.permissions = Permission(obj.read!uint); }, 56 { this.managed = obj.read!bool; }, 57 { this.mentionable = obj.read!bool; }, 58 { this.color = obj.read!uint; }, 59 ); 60 } 61 62 Snowflake getID() { 63 return this.id; 64 } 65 } 66 67 class Emoji : IModel { 68 mixin Model; 69 70 Snowflake id; 71 Guild guild; 72 string name; 73 bool requireColons; 74 bool managed; 75 76 Snowflake[] roles; 77 78 this(Client client, ref JSON obj) { 79 super(client, obj); 80 } 81 82 this(Guild guild, ref JSON obj) { 83 this.guild = guild; 84 super(guild.client, obj); 85 } 86 87 override void load(ref JSON obj) { 88 obj.keySwitch!( 89 "id", "name", "require_colons", "managed", "roles" 90 )( 91 { this.id = readSnowflake(obj); }, 92 { this.name = obj.read!string; }, 93 { this.requireColons = obj.read!bool; }, 94 { this.managed = obj.read!bool; }, 95 { this.roles = obj.read!(string[]).map!((c) => c.to!Snowflake).array; }, 96 ); 97 } 98 99 bool matches(string usage) { 100 if (this.name == ":" ~ usage ~ ":") { 101 return true; 102 } else if (this.requireColons) { 103 return false; 104 } else { 105 return this.name == usage; 106 } 107 } 108 } 109 110 class GuildMember : IModel { 111 mixin Model; 112 113 User user; 114 Guild guild; 115 string nick; 116 string joinedAt; 117 bool mute; 118 bool deaf; 119 120 Snowflake[] roles; 121 122 this(Client client, ref JSON obj) { 123 super(client, obj); 124 } 125 126 this(Guild guild, ref JSON obj) { 127 this.guild = guild; 128 super(guild.client, obj); 129 } 130 131 override void load(ref JSON obj) { 132 obj.keySwitch!( 133 "user", "guild_id", "roles", "nick", "mute", "deaf", "joined_at" 134 )( 135 { this.user = new User(this.client, obj); }, 136 { this.guild = this.client.state.guilds.get(readSnowflake(obj)); }, 137 { this.roles = obj.read!(string[]).map!((c) => c.to!Snowflake).array; }, 138 { this.nick = obj.read!string; }, 139 { this.mute = obj.read!bool; }, 140 { this.deaf = obj.read!bool; }, 141 { this.joinedAt = obj.read!string; }, 142 ); 143 144 // If the state has a user, lets use that version (and trash our local one) 145 // in theory this could leave things dirty, which isn't great... 146 if (this.client.state.users.has(this.user.id)) { 147 this.user = this.client.state.users.get(this.user.id); 148 } 149 } 150 151 Snowflake getID() { 152 return this.user.id; 153 } 154 155 bool hasRole(Role role) { 156 return this.hasRole(role.id); 157 } 158 159 bool hasRole(Snowflake id) { 160 return this.roles.canFind(id); 161 } 162 } 163 164 class Guild : IModel { 165 mixin Model; 166 167 Snowflake id; 168 Snowflake ownerID; 169 Snowflake afkChannelID; 170 Snowflake embedChannelID; 171 string name; 172 string icon; 173 string splash; 174 string region; 175 uint afkTimeout; 176 bool embedEnabled; 177 ushort verificationLevel; 178 string[] features; 179 180 bool unavailable; 181 182 // Mappings 183 GuildMemberMap members; 184 VoiceStateMap voiceStates; 185 ChannelMap channels; 186 RoleMap roles; 187 EmojiMap emojis; 188 189 override void init() { 190 this.members = new GuildMemberMap; 191 this.voiceStates = new VoiceStateMap; 192 this.channels = new ChannelMap; 193 this.roles = new RoleMap; 194 this.emojis = new EmojiMap; 195 } 196 197 override void load(ref JSON obj) { 198 obj.keySwitch!( 199 "id", "unavailable", "owner_id", "name", "icon", 200 "region", "verification_level", "afk_channel_id", 201 "splash", "afk_timeout", "channels", "roles", "members", 202 "voice_states", "emojis", "features", 203 )( 204 { this.id = readSnowflake(obj); }, 205 { this.unavailable = obj.read!bool; }, 206 { this.ownerID = readSnowflake(obj); }, 207 { this.name = obj.read!string; }, 208 { this.icon = obj.read!string; }, 209 { this.region = obj.read!string; }, 210 { this.verificationLevel = obj.read!ushort; }, 211 { this.afkChannelID = readSnowflake(obj); }, 212 { this.splash = obj.read!string; }, 213 { this.afkTimeout = obj.read!uint; }, 214 { 215 loadManyComplex!(Guild, Channel)(this, obj, (c) { this.channels[c.id] = c; }); 216 }, 217 { 218 loadManyComplex!(Guild, Role)(this, obj, (r) { this.roles[r.id] = r; }); 219 }, 220 { 221 loadManyComplex!(Guild, GuildMember)(this, obj, (m) { this.members[m.user.id] = m; }); 222 }, 223 { 224 loadMany!VoiceState(this.client, obj, (v) { this.voiceStates[v.sessionID] = v; }); 225 }, 226 { 227 loadManyComplex!(Guild, Emoji)(this, obj, (e) { this.emojis[e.id] = e; }); 228 }, 229 { this.features = obj.read!(string[]); }); 230 } 231 232 GuildMember getMember(User obj) { 233 return this.getMember(obj.id); 234 } 235 236 GuildMember getMember(Snowflake id) { 237 return this.members[id]; 238 } 239 240 Snowflake getID() { 241 return this.id; 242 } 243 244 void kick(GuildMember member) { 245 this.kick(member.user); 246 } 247 248 void kick(User user) { 249 this.client.api.guildRemoveMember(this.id, user.id); 250 } 251 }