1 module dscord.types.user; 2 3 import std.stdio, 4 std.format, 5 std.algorithm.searching; 6 7 import std.conv : to; 8 9 import dscord.types, 10 dscord.client; 11 12 alias UserMap = ModelMap!(Snowflake, User); 13 14 enum GameType : ushort { 15 DEFAULT = 0, 16 STREAMING = 1, 17 LISTENING = 2, 18 WATCHING = 3, 19 } 20 21 enum UserStatus : string { 22 ONLINE = "online", 23 IDLE = "idle", 24 DND = "dnd", 25 INVISIBLE = "invisible", 26 OFFLINE = "offline", 27 } 28 29 enum DefaultAvatarColor { 30 BLURPLE = 0, 31 GREY = 1, 32 GREEN = 2, 33 ORANGE = 3, 34 RED = 4, 35 } 36 37 class Game { 38 string name; 39 string url; 40 GameType type; 41 42 this(string name="", string url="", GameType type=GameType.DEFAULT) { 43 this.name = name; 44 this.url = url; 45 this.type = type; 46 } 47 48 // TODO: remove 49 VibeJSON dump() { 50 VibeJSON obj = VibeJSON.emptyObject; 51 52 obj["name"] = VibeJSON(this.name); 53 54 if (this.url != "") { 55 obj["url"] = VibeJSON(this.url); 56 obj["type"] = VibeJSON(cast(ushort)this.type); 57 } 58 59 return obj; 60 } 61 } 62 63 class Presence : IModel { 64 mixin Model; 65 66 User user; 67 Game game; 68 UserStatus status; 69 } 70 71 class User : IModel { 72 mixin Model; 73 74 Snowflake id; 75 string username; 76 string discriminator; 77 string avatar; 78 bool verified; 79 string email; 80 81 override string toString() { 82 return format("<User %s#%s (%s)>", this.username, this.discriminator, this.id); 83 } 84 85 string getAvatarURL(string fmt = null, size_t size = 1024) { 86 if (!this.avatar) { 87 return format("https://cdn.discordapp.com/embed/avatars/%s.png", cast(int)this.defaultAvatarColor); 88 } 89 90 if (fmt is null) { 91 fmt = this.avatar.startsWith("a_") ? "gif" : "webp"; 92 } 93 94 return format("https://cdn.discordapp.com/avatars/%s/%s.%s?size=%s", this.id, this.avatar, fmt, size); 95 } 96 97 @property DefaultAvatarColor defaultAvatarColor() { 98 auto discrimNumber = this.discriminator.to!int; 99 100 return cast(DefaultAvatarColor)(discrimNumber % DefaultAvatarColor.sizeof); 101 } 102 }