/
ThreadUpdateHandler.java
205 lines (186 loc) · 8.53 KB
/
ThreadUpdateHandler.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
193
194
195
196
197
198
199
200
201
202
203
204
205
/*
* Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
*
* 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.internal.handle;
import gnu.trove.set.TLongSet;
import net.dv8tion.jda.api.entities.channel.ChannelFlag;
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
import net.dv8tion.jda.api.events.channel.update.*;
import net.dv8tion.jda.api.utils.cache.CacheFlag;
import net.dv8tion.jda.api.utils.data.DataArray;
import net.dv8tion.jda.api.utils.data.DataObject;
import net.dv8tion.jda.internal.JDAImpl;
import net.dv8tion.jda.internal.entities.EntityBuilder;
import net.dv8tion.jda.internal.entities.channel.concrete.ThreadChannelImpl;
import net.dv8tion.jda.internal.utils.Helpers;
import net.dv8tion.jda.internal.utils.cache.SnowflakeCacheViewImpl;
import net.dv8tion.jda.internal.utils.cache.SortedSnowflakeCacheViewImpl;
import java.util.List;
import java.util.Objects;
import java.util.stream.LongStream;
public class ThreadUpdateHandler extends SocketHandler
{
public ThreadUpdateHandler(JDAImpl api)
{
super(api);
}
@Override
protected Long handleInternally(DataObject content)
{
long guildId = content.getLong("guild_id");
if (api.getGuildSetupController().isLocked(guildId))
return guildId;
final long threadId = content.getLong("id");
ThreadChannelImpl thread = (ThreadChannelImpl) getJDA().getThreadChannelById(threadId);
//If the thread is missing then that means that the bot started up while the thread was archived
// thus it didn't get the thread. Now that it's been unarchived we've been given the entire thread and need to build it.
//Refer to the documentation for more info: https://discord.com/developers/docs/topics/threads#unarchiving-a-thread
if (thread == null)
{
// This seems to never be true but its better to check
if (content.getObject("thread_metadata").getBoolean("archived"))
return null;
//Technically, when the ThreadChannel is unarchived the archive_timestamp (getTimeArchiveInfoLastModified) changes
// as well, but we don't have the original value because we didn't have the thread in memory, so we can't
// provide an entirely accurate ChannelUpdateArchiveTimestampEvent. Not sure how much that'll matter.
try
{
thread = (ThreadChannelImpl) api.getEntityBuilder().createThreadChannel(content, guildId);
api.handleEvent(
new ChannelUpdateArchivedEvent(
api, responseNumber,
thread, true, false));
}
catch (IllegalArgumentException ex)
{
if (EntityBuilder.MISSING_CHANNEL.equals(ex.getMessage()))
{
long parentId = content.getUnsignedLong("parent_id", 0L);
EventCache.LOG.debug("Caching THREAD_UPDATE for a thread with uncached parent. Parent ID: {} JSON: {}", parentId, content);
api.getEventCache().cache(EventCache.Type.CHANNEL, parentId, responseNumber, allContent, this::handle);
return null;
}
throw ex;
}
return null;
}
final DataObject threadMetadata = content.getObject("thread_metadata");
final String name = content.getString("name");
final int flags = content.getInt("flags", 0);
final ThreadChannel.AutoArchiveDuration autoArchiveDuration = ThreadChannel.AutoArchiveDuration.fromKey(threadMetadata.getInt("auto_archive_duration"));
final boolean locked = threadMetadata.getBoolean("locked");
final boolean archived = threadMetadata.getBoolean("archived");
final boolean invitable = threadMetadata.getBoolean("invitable");
final long archiveTimestamp = Helpers.toTimestamp(threadMetadata.getString("archive_timestamp"));
final int slowmode = content.getInt("rate_limit_per_user", 0);
final String oldName = thread.getName();
final ThreadChannel.AutoArchiveDuration oldAutoArchiveDuration = thread.getAutoArchiveDuration();
final boolean oldLocked = thread.isLocked();
final boolean oldArchived = thread.isArchived();
final boolean oldInvitable = !thread.isPublic() && thread.isInvitable();
final long oldArchiveTimestamp = thread.getArchiveTimestamp();
final int oldSlowmode = thread.getSlowmode();
final int oldFlags = thread.getRawFlags();
if (!Objects.equals(oldName, name))
{
thread.setName(name);
api.handleEvent(
new ChannelUpdateNameEvent(
getJDA(), responseNumber,
thread, oldName, name));
}
if (oldFlags != flags)
{
thread.setFlags(flags);
api.handleEvent(
new ChannelUpdateFlagsEvent(
getJDA(), responseNumber,
thread, ChannelFlag.fromRaw(oldFlags), ChannelFlag.fromRaw(flags)));
}
if (oldSlowmode != slowmode)
{
thread.setSlowmode(slowmode);
api.handleEvent(
new ChannelUpdateSlowmodeEvent(
api, responseNumber,
thread, oldSlowmode, slowmode));
}
if (oldAutoArchiveDuration != autoArchiveDuration)
{
thread.setAutoArchiveDuration(autoArchiveDuration);
api.handleEvent(
new ChannelUpdateAutoArchiveDurationEvent(
api, responseNumber,
thread, oldAutoArchiveDuration, autoArchiveDuration));
}
if (oldLocked != locked)
{
thread.setLocked(locked);
api.handleEvent(
new ChannelUpdateLockedEvent(
api, responseNumber,
thread, oldLocked, locked));
}
if (oldArchived != archived)
{
thread.setArchived(archived);
api.handleEvent(
new ChannelUpdateArchivedEvent(
api, responseNumber,
thread, oldArchived, archived));
}
if (oldArchiveTimestamp != archiveTimestamp)
{
thread.setArchiveTimestamp(archiveTimestamp);
api.handleEvent(
new ChannelUpdateArchiveTimestampEvent(
api, responseNumber,
thread, oldArchiveTimestamp, archiveTimestamp));
}
if (oldInvitable != invitable)
{
thread.setInvitable(invitable);
api.handleEvent(
new ChannelUpdateInvitableEvent(
api, responseNumber,
thread, oldInvitable, invitable));
}
if (api.isCacheFlagSet(CacheFlag.FORUM_TAGS) && !content.isNull("applied_tags"))
{
final TLongSet oldTags = thread.getAppliedTagsSet();
thread.setAppliedTags(content.getArray("applied_tags")
.stream(DataArray::getUnsignedLong)
.mapToLong(Long::longValue));
final TLongSet tags = thread.getAppliedTagsSet();
if (!oldTags.equals(tags))
{
List<Long> oldTagList = LongStream.of(oldTags.toArray()).boxed().collect(Helpers.toUnmodifiableList());
List<Long> newTagList = LongStream.of(tags.toArray()).boxed().collect(Helpers.toUnmodifiableList());
api.handleEvent(
new ChannelUpdateAppliedTagsEvent(
api, responseNumber,
thread, oldTagList, newTagList));
}
}
if (thread.isArchived())
{
SortedSnowflakeCacheViewImpl<ThreadChannel> guildView = thread.getGuild().getThreadChannelsView();
SnowflakeCacheViewImpl<ThreadChannel> globalView = api.getThreadChannelsView();
guildView.remove(threadId);
globalView.remove(threadId);
}
return null;
}
}