1 /**
2   The top API abstraction encompassing REST, WS/Gateway, and state tracking.
3 */
4 module dscord.client;
5 
6 import std.stdio;
7 
8 public import std.experimental.logger;
9 
10 import std.algorithm.iteration;
11 
12 import dscord.api,
13        dscord.types,
14        dscord.state,
15        dscord.voice,
16        dscord.gateway,
17        dscord.util.emitter;
18 
19 
20 /**
21   Struct containing configuration for Gateway sharding.
22 */
23 struct ShardInfo {
24   /** This shards number. */
25   ushort shard = 0;
26 
27   /** Total number of shards. */
28   ushort numShards = 1;
29 }
30 
31 @JSONIgnore
32 class Client {
33   /** Base log */
34   Logger  log;
35 
36   /** Bot Authentication token */
37   string  token;
38 
39   /** Sharding configuration */
40   ShardInfo* shardInfo;
41 
42   /** APIClient instance */
43   APIClient      api;
44 
45   /** GatewayClient instance */
46   GatewayClient  gw;
47 
48   /** State instance */
49   State  state;
50 
51   /** Mapping of voice connections */
52   VoiceClient[Snowflake]  voiceConns;
53 
54   /** Emitter for gateway events */
55   Emitter  events;
56 
57   this(string token, LogLevel lvl=LogLevel.all, ShardInfo* shardInfo = null) {
58     this.log = new FileLogger(stdout, lvl);
59     this.token = token;
60     this.shardInfo = shardInfo ? shardInfo : new ShardInfo();
61 
62     this.api = new APIClient(this);
63     this.gw = new GatewayClient(this);
64     this.state = new State(this);
65   }
66 
67   /**
68     Returns the current user.
69   */
70   @property User me() {
71     return this.state.me;
72   }
73 
74   /**
75     Gets an array of messages for a given channel.
76 
77     Params:
78       channelID = the channelID all the messages originate from.
79       limit = the number of messages to retrieve.
80       msgID = the message which other messages are selected, with respect to the filter
81       filter = get messages before, around, or after the supplied msgID
82   */
83   Message[] getMessages(Snowflake channelID, uint limit = 100, Snowflake msgID = 0, MessageFilter filter = MessageFilter.BEFORE) {
84     return this.api.channelsMessagesList(channelID, limit, filter, msgID);
85   }
86 
87   /**
88     Deletes an array of messages for a given channel, properly bulking them
89     if required.
90 
91     Params:
92       channelID = the channelID all the messages originate from.
93       messages = the array of messages.
94   */
95   void deleteMessages(Snowflake channelID, Message[] messages) {
96     Snowflake[] msgIDs;
97 
98     foreach(message; messages){
99       msgIDs ~= message.id;
100     }
101     
102     return deleteMessages(channelID, msgIDs);
103   }
104 
105   /**
106     Deletes an array of message IDs for a given channel, properly bulking them
107     if required.
108 
109     Params:
110       channelID = the channelID all the messages originate from
111       msgIDs = the array of message IDs
112   */
113   void deleteMessages(Snowflake channelID, Snowflake[] msgIDs) {
114     if (msgIDs.length <= 2) {
115       msgIDs.each!(x => this.api.channelsMessagesDelete(channelID, x));
116     } else {
117       this.api.channelsMessagesDeleteBulk(channelID, msgIDs);
118     }
119   }
120 
121   void updateStatus(uint idleSince, Game game=null) {
122     this.gw.send(new StatusUpdate(idleSince, game));
123   }
124 }