Implement reactions

This commit is contained in:
Jeremy Zhang 2018-07-27 08:57:54 +00:00
parent 4aa785d4cc
commit 1629a8982c
7 changed files with 174 additions and 2 deletions

View File

@ -102,6 +102,18 @@ class Titan(discord.AutoShardedClient):
self.delete_list.append(message.id) self.delete_list.append(message.id)
await self.redisqueue.delete_message(message) await self.redisqueue.delete_message(message)
await self.socketio.on_message_delete(message) await self.socketio.on_message_delete(message)
async def on_reaction_add(self, reaction, user):
await self.redisqueue.update_message(reaction.message)
await self.socketio.on_reaction_add(reaction.message)
async def on_reaction_remove(self, reaction, user):
await self.redisqueue.update_message(reaction.message)
await self.socketio.on_reaction_remove(reaction.message)
async def on_reaction_clear(self, message, reactions):
await self.redisqueue.update_message(message)
await self.socketio.on_reaction_clear(message)
async def on_guild_join(self, guild): async def on_guild_join(self, guild):
await self.redisqueue.update_guild(guild) await self.redisqueue.update_guild(guild)
@ -206,6 +218,31 @@ class Titan(discord.AutoShardedClient):
msg = discord.Message(channel=channel, state=self._connection, data=data) # Procreate a fake message object msg = discord.Message(channel=channel, state=self._connection, data=data) # Procreate a fake message object
await self.on_message_delete(msg) await self.on_message_delete(msg)
async def on_raw_reaction_add(self, payload):
message_id = payload.message_id
if not self.in_messages_cache(message_id):
channel = self.get_channel(payload.channel_id)
message = await channel.get_message(message_id)
await self.on_reaction_add(message.reactions[0], None)
async def on_raw_reaction_remove(self, payload):
message_id = payload.message_id
if not self.in_messages_cache(message_id):
partial = payload.emoji
emoji = self._connection._upgrade_partial_emoji(partial)
channel = self.get_channel(payload.channel_id)
message = await channel.get_message(message_id)
message._add_reaction({"me": payload.user_id == self.user.id}, emoji, payload.user_id)
reaction = message._remove_reaction({}, emoji, payload.user_id)
await self.on_reaction_remove(reaction, None)
async def on_raw_reaction_clear(self, payload):
message_id = payload.message_id
if not self.in_messages_cache(message_id):
channel = self.get_channel(payload.channel_id)
message = await channel.get_message(message_id)
await self.on_reaction_clear(message, [])
def in_messages_cache(self, msg_id): def in_messages_cache(self, msg_id):
for msg in self._connection._messages: for msg in self._connection._messages:
if msg.id == msg_id: if msg.id == msg_id:

View File

@ -22,6 +22,21 @@ class SocketIOInterface:
msg = get_formatted_message(message) msg = get_formatted_message(message)
await self.io.emit('MESSAGE_UPDATE', data=msg, room=str("CHANNEL_"+str(message.channel.id)), namespace='/gateway') await self.io.emit('MESSAGE_UPDATE', data=msg, room=str("CHANNEL_"+str(message.channel.id)), namespace='/gateway')
async def on_reaction_add(self, message):
if message.guild:
msg = get_formatted_message(message)
await self.io.emit('MESSAGE_REACTION_ADD', data=msg, room=str("CHANNEL_"+str(message.channel.id)), namespace='/gateway')
async def on_reaction_remove(self, message):
if message.guild:
msg = get_formatted_message(message)
await self.io.emit('MESSAGE_REACTION_REMOVE', data=msg, room=str("CHANNEL_"+str(message.channel.id)), namespace='/gateway')
async def on_reaction_clear(self, message):
if message.guild:
msg = get_formatted_message(message)
await self.io.emit('MESSAGE_REACTION_REMOVE_ALL', data=msg, room=str("CHANNEL_"+str(message.channel.id)), namespace='/gateway')
async def on_guild_member_add(self, member): async def on_guild_member_add(self, member):
user = get_formatted_user(member) user = get_formatted_user(member)
await self.io.emit('GUILD_MEMBER_ADD', data=user, room=str("GUILD_"+str(member.guild.id)), namespace='/gateway') await self.io.emit('GUILD_MEMBER_ADD', data=user, room=str("GUILD_"+str(member.guild.id)), namespace='/gateway')

View File

@ -36,6 +36,8 @@ def get_formatted_message(message):
member = message.guild.get_member(mention["id"]) member = message.guild.get_member(mention["id"])
if member: if member:
mention["nickname"] = member.nick mention["nickname"] = member.nick
if hasattr(message, "reactions"):
msg["reactions"] = get_message_reactions(message.reactions)
return msg return msg
def get_formatted_user(user): def get_formatted_user(user):
@ -246,4 +248,26 @@ def get_embeds_list(embeds):
em = [] em = []
for e in embeds: for e in embeds:
em.append(e.to_dict()) em.append(e.to_dict())
return em return em
def get_message_reactions(reactions):
reacts = []
for reaction in reactions:
reacts.append({
"emoji": get_partial_emoji(reaction.emoji),
"count": reaction.count
})
return reacts
def get_partial_emoji(emoji):
emote = {
"animated": False,
"id": None,
"name": str(emoji)
}
if isinstance(emoji, str):
return emote
emote["animated"] = emoji.animated
emote["id"] = str(emoji.id)
emote["name"] = emoji.name
return emote

View File

@ -59,6 +59,7 @@ class RedisQueue:
"channel_id": str(x["channel_id"]), "channel_id": str(x["channel_id"]),
"mentions": x["mentions"], "mentions": x["mentions"],
"embeds": x["embeds"], "embeds": x["embeds"],
"reactions": x["reactions"]
} }
if message["author"]["id"] not in guild_members: if message["author"]["id"] not in guild_members:
member = self.get_guild_member(guild_id, message["author"]["id"]) member = self.get_guild_member(guild_id, message["author"]["id"])

View File

@ -793,6 +793,42 @@ p.mentioned span.chatmessage {
max-width: 400px; max-width: 400px;
} }
#chatcontent span.reactions {
display: block;
}
#chatcontent span.reactions .reaction {
background-color: rgba(0, 0, 0, 0.1);
font-size: 12pt;
border-radius: 5px;
margin-left: 6px;
padding-left: 3px;
padding-right: 3px;
color: #C3C4C5;
cursor: pointer;
height: 27px;
display: inline-block;
min-width: 50px;
}
#chatcontent span.reactions .reaction:hover {
transform: scale(1.3);
}
#chatcontent span.reactions .reaction:hover:active {
transform: scale(0.9);
}
#chatcontent span.reactions .reaction img {
width: 18px;
vertical-align: middle;
}
#chatcontent span.reactions .reaction .count {
float: right;
margin-right: 6px;
}
.wdt-emoji-popup { .wdt-emoji-popup {
position: fixed; position: fixed;
bottom: 5%; bottom: 5%;

View File

@ -1152,6 +1152,29 @@
} }
return emb; return emb;
} }
function parse_message_reactions(reactions) {
var reacts = []
var template = $("#mustache_reactionchip").html();
Mustache.parse(template);
for (var i = 0; i < reactions.length; i++) {
var disreact = reactions[i];
var emoji = disreact.emoji;
if (emoji.id) {
disreact.img_url = "https://cdn.discordapp.com/emojis/" + emoji.id;
if (emoji.animated) {
disreact.img_url += ".gif";
} else {
disreact.img_url += ".png";
}
} else {
disreact.img_url = $(twemoji.parse(emoji.name)).attr("src");
}
var rendered = Mustache.render(template, disreact);
reacts.push(rendered);
}
return reacts;
}
function fill_discord_messages(messages, jumpscroll, replace) { function fill_discord_messages(messages, jumpscroll, replace) {
if (replace === undefined) { if (replace === undefined) {
@ -1215,6 +1238,11 @@
for(var j = 0; j < embeds.length; j++) { for(var j = 0; j < embeds.length; j++) {
$("#discordmessage_"+message.id).parent().find("span.embeds").append(embeds[j]); $("#discordmessage_"+message.id).parent().find("span.embeds").append(embeds[j]);
} }
var reactions = parse_message_reactions(message.reactions);
$("#discordmessage_"+message.id).parent().find("span.reactions").text("");
for(var j = 0; j < reactions.length; j++) {
$("#discordmessage_"+message.id).parent().find("span.reactions").append(reactions[j]);
}
var usrcachekey = username + "#" + message.author.discriminator; var usrcachekey = username + "#" + message.author.discriminator;
if (usrcachekey.startsWith("(Titan Dev) ")) { if (usrcachekey.startsWith("(Titan Dev) ")) {
usrcachekey = usrcachekey.substr(12); usrcachekey = usrcachekey.substr(12);
@ -1783,6 +1811,33 @@
fill_discord_messages([msg], false, msgelem_parent); fill_discord_messages([msg], false, msgelem_parent);
}); });
socket.on("MESSAGE_REACTION_ADD", function (msg) {
var msgelem = $("#discordmessage_"+msg.id);
if (msgelem.length == 0) {
return;
}
var msgelem_parent = msgelem.parent();
fill_discord_messages([msg], false, msgelem_parent);
});
socket.on("MESSAGE_REACTION_REMOVE", function (msg) {
var msgelem = $("#discordmessage_"+msg.id);
if (msgelem.length == 0) {
return;
}
var msgelem_parent = msgelem.parent();
fill_discord_messages([msg], false, msgelem_parent);
});
socket.on("MESSAGE_REACTION_REMOVE_ALL", function (msg) {
var msgelem = $("#discordmessage_"+msg.id);
if (msgelem.length == 0) {
return;
}
var msgelem_parent = msgelem.parent();
fill_discord_messages([msg], false, msgelem_parent);
});
socket.on("GUILD_MEMBER_ADD", function (usr) { socket.on("GUILD_MEMBER_ADD", function (usr) {
if (usr.status != "offline") { if (usr.status != "offline") {
discord_users_list.push(usr); discord_users_list.push(usr);

View File

@ -350,7 +350,7 @@
</script> </script>
<script id="mustache_usermessage" type="text/template"> <script id="mustache_usermessage" type="text/template">
<p><img class="authoravatar" src="{{avatar}}"> <span class="chatusername"><span class="authorname">{{username}}</span><span class="authorhash">#</span><span class="authordiscriminator">{{discriminator}}</span></span> <span id="discordmessage_{{id}}" title="{{full_timestamp}}" class="chattimestamp">{{time}}</span> <span class="chatmessage">{{{content}}}</span><span class="embeds"></span></p> <p><img class="authoravatar" src="{{avatar}}"> <span class="chatusername"><span class="authorname">{{username}}</span><span class="authorhash">#</span><span class="authordiscriminator">{{discriminator}}</span></span> <span id="discordmessage_{{id}}" title="{{full_timestamp}}" class="chattimestamp">{{time}}</span> <span class="chatmessage">{{{content}}}</span><span class="embeds"></span><span class="reactions"></span></p>
</script> </script>
<script id="mustache_memberrole" type="text/template"> <script id="mustache_memberrole" type="text/template">
@ -481,6 +481,10 @@
</span> </span>
</div> </div>
</script> </script>
<script id="mustache_reactionchip" type="text/template">
<span class="reaction tooltipped" data-position="top" data-delay="200" data-tooltip="{{#emoji.id}}:{{/emoji.id}}{{emoji.name}}{{#emoji.id}}:{{/emoji.id}}"><img src="{{img_url}}"> <span class="count">{{count}}</span></span>
</script>
{% endraw %} {% endraw %}
<script> <script>