1 /** 2 Utilties for handling/listening to events through the dcord bot interface. 3 */ 4 5 module dcord.bot.listener; 6 7 import std.variant, 8 std..string, 9 std.array; 10 11 import dcord.types, 12 dcord.gateway, 13 dcord.util.emitter; 14 15 /** 16 UDA that can be used on a Plugin, informing it that the function will handle 17 all events of type T. 18 19 Params: 20 T = Event type to listen for 21 */ 22 ListenerDef!T Listener(T, EmitterOrder order = EmitterOrder.UNSPECIFIED)() { // stfu 23 return ListenerDef!(T)(T.stringof, order, (event, func) { 24 func(event.get!(T)); 25 }); 26 } 27 28 /** 29 Utility struct returned by the UDA. 30 */ 31 struct ListenerDef(T) { 32 string clsName; 33 EmitterOrder order; 34 void delegate(Variant, void delegate(T)) func; 35 } 36 37 /** 38 A ListenerObject represents the configuration/state for a single listener. 39 */ 40 class ListenerObject { 41 /** The class name of the event this listener is for */ 42 string clsName; 43 44 /// Emitter order for this event listener 45 EmitterOrder order; 46 47 /** EventListener function for this Listener */ 48 EventListener listener; 49 50 /** Utility variant caller for converting event type */ 51 void delegate(Variant v) func; 52 53 this(string clsName, EmitterOrder order, void delegate(Variant v) func) { 54 this.clsName = clsName; 55 this.func = func; 56 } 57 } 58 59 /** 60 The Listenable template is a virtual implementation which handles the listener 61 UDAs, storing them within a local "listeners" mapping. 62 */ 63 mixin template Listenable() { 64 ListenerObject[] listeners; 65 66 /// Load all listeners. 67 void loadListeners(T)() { 68 // TODO: make this cleaner 69 foreach (mem; __traits(allMembers, T)) { 70 foreach(attr; __traits(getAttributes, __traits(getMember, T, mem))) { 71 static if (__traits(hasMember, attr, "clsName")) { 72 this.registerListener(new ListenerObject(attr.clsName, attr.order, (v) { 73 attr.func(v, mixin("&(cast(T)this)." ~ mem)); 74 })); 75 } 76 } 77 } 78 } 79 80 /// Registers a listener from a ListenerObject 81 void registerListener(ListenerObject obj) { 82 this.listeners ~= obj; 83 } 84 }