/
PresenceUpdateHandler.java
192 lines (179 loc) · 8.8 KB
/
PresenceUpdateHandler.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*
* Copyright 2015-2017 Austin Keener & Michael Ritter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.dv8tion.jda.core.handle;
import net.dv8tion.jda.core.OnlineStatus;
import net.dv8tion.jda.core.entities.Game;
import net.dv8tion.jda.core.entities.impl.*;
import net.dv8tion.jda.core.events.user.UserAvatarUpdateEvent;
import net.dv8tion.jda.core.events.user.UserGameUpdateEvent;
import net.dv8tion.jda.core.events.user.UserNameUpdateEvent;
import net.dv8tion.jda.core.events.user.UserOnlineStatusUpdateEvent;
import net.dv8tion.jda.core.requests.GuildLock;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
public class PresenceUpdateHandler extends SocketHandler
{
public PresenceUpdateHandler(JDAImpl api)
{
super(api);
}
@Override
protected Long handleInternally(JSONObject content)
{
//Do a pre-check to see if this is for a Guild, and if it is, if the guild is currently locked.
if (content.has("guild_id"))
{
final long guildId = content.getLong("guild_id");
if (api.getGuildLock().isLocked(guildId))
return guildId;
}
JSONObject jsonUser = content.getJSONObject("user");
final long userId = jsonUser.getLong("id");
UserImpl user = (UserImpl) api.getUserMap().get(userId);
//If we do know about the user, lets update the user's specific info.
// Afterwards, we will see if we already have them cached in the specific guild
// or Relation. If not, we'll cache the OnlineStatus and Game for later handling
// unless OnlineStatus is OFFLINE, in which case we probably received this event
// due to a User leaving a guild or no longer being a relation.
if (user != null)
{
if (jsonUser.has("username"))
{
String name = jsonUser.getString("username");
String discriminator = jsonUser.get("discriminator").toString();
String avatarId = jsonUser.isNull("avatar") ? null : jsonUser.getString("avatar");
if (!user.getName().equals(name))
{
String oldUsername = user.getName();
String oldDiscriminator = user.getDiscriminator();
user.setName(name);
user.setDiscriminator(discriminator);
api.getEventManager().handle(
new UserNameUpdateEvent(
api, responseNumber,
user, oldUsername, oldDiscriminator));
}
String oldAvatar = user.getAvatarId();
if (!(avatarId == null && oldAvatar == null) && !StringUtils.equals(avatarId, oldAvatar))
{
String oldAvatarId = user.getAvatarId();
user.setAvatarId(avatarId);
api.getEventManager().handle(
new UserAvatarUpdateEvent(
api, responseNumber,
user, oldAvatarId));
}
}
//Now that we've update the User's info, lets see if we need to set the specific Presence information.
// This is stored in the Member or Relation objects.
String gameName = null;
String gameUrl = null;
Game.GameType type = null;
if ( !content.isNull("game") && !content.getJSONObject("game").isNull("name") )
{
gameName = content.getJSONObject("game").get("name").toString();
gameUrl = ( content.getJSONObject("game").isNull("url") ? null : content.getJSONObject("game").get("url").toString() );
try
{
type = content.getJSONObject("game").isNull("type")
? Game.GameType.DEFAULT
: Game.GameType.fromKey(Integer.parseInt(content.getJSONObject("game").get("type").toString()));
}
catch (NumberFormatException ex)
{
type = Game.GameType.DEFAULT;
}
}
Game nextGame = (gameName == null
? null
: new GameImpl(gameName, gameUrl, type));
OnlineStatus status = OnlineStatus.fromKey(content.getString("status"));
//If we are in a Guild, then we will use Member.
// If we aren't we'll be dealing with the Relation system.
if (content.has("guild_id"))
{
GuildImpl guild = (GuildImpl) api.getGuildById(content.getLong("guild_id"));
MemberImpl member = (MemberImpl) guild.getMember(user);
//If the Member is null, then User isn't in the Guild.
//This is either because this PRESENCE_UPDATE was received before the GUILD_MEMBER_ADD event
// or because a Member recently left and this PRESENCE_UPDATE came after the GUILD_MEMBER_REMOVE event.
//If it is because a Member recently left, then the status should be OFFLINE. As such, we will ignore
// the event if this is the case. If the status isn't OFFLINE, we will cache and use it when the
// Member object is setup during GUILD_MEMBER_ADD
if (member == null)
{
//Cache the presence and return to finish up.
if (status != OnlineStatus.OFFLINE)
{
guild.getCachedPresenceMap().put(userId, content);
return null;
}
}
else
{
//The member is already cached, so modify the presence values and fire events as needed.
if (!member.getOnlineStatus().equals(status))
{
OnlineStatus oldStatus = member.getOnlineStatus();
member.setOnlineStatus(status);
api.getEventManager().handle(
new UserOnlineStatusUpdateEvent(
api, responseNumber,
user, guild, oldStatus));
}
if(member.getGame() == null ? nextGame != null : !member.getGame().equals(nextGame))
{
Game oldGame = member.getGame();
member.setGame(nextGame);
api.getEventManager().handle(
new UserGameUpdateEvent(
api, responseNumber,
user, guild, oldGame));
}
}
}
else
{
//In this case, this PRESENCE_UPDATE is for a Relation.
}
}
else
{
//In this case, we don't have the User cached, which means that we can't update the User's information.
// This is most likely because this PRESENCE_UPDATE came before the GUILD_MEMBER_ADD that would have added
// this User to our User cache. Or, it could have come after a GUILD_MEMBER_REMOVE that caused the User
// to be removed from JDA's central User cache because there were no more connected Guilds. If this is
// the case, then the OnlineStatus will be OFFLINE and we can ignore this event.
//Either way, we don't have the User cached so we need to cache the Presence information if
// the OnlineStatus is not OFFLINE.
//If the OnlineStatus is OFFLINE, ignore the event and return.
OnlineStatus status = OnlineStatus.fromKey(content.getString("status"));
if (status == OnlineStatus.OFFLINE)
return null;
//If this was for a Guild, cache it in the Guild for later use in GUILD_MEMBER_ADD
if (content.has("guild_id"))
{
GuildImpl guild = (GuildImpl) api.getGuildById(content.getLong("guild_id"));
guild.getCachedPresenceMap().put(userId, content);
}
else
{
//cache in relationship stuff
}
}
return null;
}
}