Capture user avatars and additional channel info (topic, nsfw, position)

Co-authored-by: chylex <contact@chylex.com>
This commit is contained in:
denetii 2020-06-25 08:02:40 -03:00 committed by GitHub
parent 2ea32d6097
commit 64588b3634
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 117 additions and 24 deletions

View File

@ -10,6 +10,8 @@ enableFormatting
_enableFormatting
enableAnimatedEmoji
_enableAnimatedEmoji
enableUserAvatars
_enableUserAvatars
DHT_LOADED
DHT_EMBEDDED
meta
@ -28,9 +30,13 @@ t
d
te
tag
avatar
author
type
state
position
topic
nsfw
id
username
bot

View File

@ -129,7 +129,8 @@ var DISCORD = (function(){
"server": name,
"channel": name,
"id": link,
"type": (icon && (icon.src.includes("/channel-icons/") || icon.src.includes("/assets/"))) ? "GROUP" : "DM"
"type": (icon && (icon.src.includes("/channel-icons/") || icon.src.includes("/assets/"))) ? "GROUP" : "DM",
"extra": {}
};
}
else{
@ -152,7 +153,12 @@ var DISCORD = (function(){
"server": channelListEle.querySelector("header > h1").innerText,
"channel": channelObj.name,
"id": channelObj.id,
"type": "SERVER"
"type": "SERVER",
"extra": {
"position": channelObj.position,
"topic": channelObj.topic,
"nsfw": channelObj.nsfw
}
};
}

View File

@ -7,6 +7,7 @@
* users: {
* <discord user id>: {
* name: <user name>,
* avatar: <user icon>,
* tag: <user discriminator> // only present if not a bot
* }, ...
* },
@ -27,7 +28,10 @@
* channels: {
* <discord channel id>: {
* server: <server index in the meta.servers array>,
* name: <channel name>
* name: <channel name>,
* position: <order in channel list>, // only present if server type == SERVER
* topic: <channel topic>, // only present if server type == SERVER
* nsfw: <channel NSFW status> // only present if server type == SERVER
* }, ...
* }
* },
@ -103,7 +107,7 @@ class SAVEFILE{
return parsedObj && typeof parsedObj.meta === "object" && typeof parsedObj.data === "object";
}
findOrRegisterUser(userId, userName, userDiscriminator){
findOrRegisterUser(userId, userName, userDiscriminator, userAvatar){
if (!(userId in this.meta.users)){
this.meta.users[userId] = {
"name": userName
@ -113,6 +117,10 @@ class SAVEFILE{
this.meta.users[userId].tag = userDiscriminator;
}
if (userAvatar){
this.meta.users[userId].avatar = userAvatar;
}
this.meta.userindex.push(userId);
return this.tmp.userlookup[userId] = this.meta.userindex.length-1;
}
@ -140,7 +148,7 @@ class SAVEFILE{
}
}
tryRegisterChannel(serverIndex, channelId, channelName){
tryRegisterChannel(serverIndex, channelId, channelName, extraInfo){
if (!this.meta.servers[serverIndex]){
return undefined;
}
@ -153,6 +161,18 @@ class SAVEFILE{
"name": channelName
};
if (extraInfo.position){
this.meta.channels[channelId].position = extraInfo.position;
}
if (extraInfo.topic){
this.meta.channels[channelId].topic = extraInfo.topic;
}
if (extraInfo.nsfw){
this.meta.channels[channelId].nsfw = extraInfo.nsfw;
}
this.tmp.channelkeys.add(channelId);
return true;
}
@ -171,7 +191,7 @@ class SAVEFILE{
var author = discordMessage.author;
var obj = {
u: this.findOrRegisterUser(author.id, author.username, author.bot ? null : author.discriminator),
u: this.findOrRegisterUser(author.id, author.username, author.bot ? null : author.discriminator, author.avatar),
t: discordMessage.timestamp.toDate().getTime()
};
@ -244,12 +264,13 @@ class SAVEFILE{
for(var userId in obj.meta.users){
var oldUser = obj.meta.users[userId];
userMap[obj.meta.userindex.findIndex(id => id == userId)] = this.findOrRegisterUser(userId, oldUser.name, oldUser.tag);
userMap[obj.meta.userindex.findIndex(id => id == userId)] = this.findOrRegisterUser(userId, oldUser.name, oldUser.tag, oldUser.avatar);
}
for(var channelId in obj.meta.channels){
var oldServer = obj.meta.servers[obj.meta.channels[channelId].server];
this.tryRegisterChannel(this.findOrRegisterServer(oldServer.name, oldServer.type), channelId, obj.meta.channels[channelId].name);
var oldChannel = obj.meta.channels[channelId];
this.tryRegisterChannel(this.findOrRegisterServer(oldServer.name, oldServer.type), channelId, oldChannel.name, oldChannel /* filtered later */);
}
for(var channelId in obj.data){

View File

@ -79,10 +79,10 @@ var STATE = (function(){
/*
* Registers a Discord server and channel.
*/
addDiscordChannel(serverName, serverType, channelId, channelName){
addDiscordChannel(serverName, serverType, channelId, channelName, extraInfo){
var serverIndex = this.getSavefile().findOrRegisterServer(serverName, serverType);
if (this.getSavefile().tryRegisterChannel(serverIndex, channelId, channelName) === true){
if (this.getSavefile().tryRegisterChannel(serverIndex, channelId, channelName, extraInfo) === true){
triggerStateChanged("data", "channel");
}
}

View File

@ -38,7 +38,7 @@ DISCORD.setupMessageUpdateCallback(hasMoreMessages => {
return;
}
STATE.addDiscordChannel(info.server, info.type, info.id, info.channel);
STATE.addDiscordChannel(info.server, info.type, info.id, info.channel, info.extra);
let messages = DISCORD.getMessages();
@ -99,7 +99,7 @@ STATE.onStateChanged((type, enabled) => {
let messages = DISCORD.getMessages();
if (messages != null){
STATE.addDiscordChannel(info.server, info.type, info.id, info.channel);
STATE.addDiscordChannel(info.server, info.type, info.id, info.channel, info.extra);
STATE.addDiscordMessages(info.id, messages);
}
else{

View File

@ -32,7 +32,9 @@ var DISCORD = (function(){
var templateChannelServer;
var templateChannelPrivate;
var templateMessage;
var templateMessageNoAvatar;
var templateMessageWithAvatar;
var templateUserAvatar;
var templateEmbedImage;
var templateEmbedRich;
var templateEmbedRichNoDescription;
@ -43,25 +45,39 @@ var DISCORD = (function(){
setup: function(){
templateChannelServer = new TEMPLATE([
"<div data-channel='{id}'>",
"<div class='info'><strong class='name'>#{name}</strong><span class='msgcount'>{msgcount}</span></div>",
"<div class='info' title='{topic}'><strong class='name'>#{name}</strong>{nsfw}<span class='tag'>{msgcount}</span></div>",
"<span class='server'>{server.name} ({server.type})</span>",
"</div>"
].join(""));
templateChannelPrivate = new TEMPLATE([
"<div data-channel='{id}'>",
"<div class='info'><strong class='name'>{name}</strong><span class='msgcount'>{msgcount}</span></div>",
"<div class='info'><strong class='name'>{name}</strong><span class='tag'>{msgcount}</span></div>",
"<span class='server'>({server.type})</span>",
"</div>"
].join(""));
templateMessage = new TEMPLATE([
templateMessageNoAvatar = new TEMPLATE([
"<div>",
"<h2><strong class='username'>{user.name}</strong><span class='info time'>{timestamp}</span>{edit}{jump}</h2>",
"<h2><strong class='username' title='#{user.tag}'>{user.name}</strong><span class='info time'>{timestamp}</span>{edit}{jump}</h2>",
"<div class='message'>{contents}{embeds}{attachments}</div>",
"</div>"
].join(""));
templateMessageWithAvatar = new TEMPLATE([
"<div class='avatar-wrapper'>",
"<div class='avatar'>{avatar}</div>",
"<div>",
"<h2><strong class='username' title='#{user.tag}'>{user.name}</strong><span class='info time'>{timestamp}</span>{edit}{jump}</h2>",
"<div class='message'>{contents}{embeds}{attachments}</div>",
"</div>",
"</div>"
].join(""));
templateUserAvatar = new TEMPLATE([
"<img src='https://cdn.discordapp.com/avatars/{id}/{path}.webp?size=128'>"
].join(""));
templateEmbedImage = new TEMPLATE([
"<a href='{url}' class='embed thumbnail'><img src='{url}' alt='(image attachment not found)'></a><br>"
].join(""));
@ -94,12 +110,18 @@ var DISCORD = (function(){
case "DM": return "user";
}
}
else if (property === "nsfw"){
return value ? "<span class='tag'>NSFW</span>" : "";
}
});
},
getMessageHTML: function(message){
return templateMessage.apply(message, (property, value) => {
if (property === "timestamp"){
return (STATE.settings.enableUserAvatars ? templateMessageWithAvatar : templateMessageNoAvatar).apply(message, (property, value) => {
if (property === "avatar"){
return value ? templateUserAvatar.apply(value) : "";
}
else if (property === "timestamp"){
return getHumanReadableTime(value);
}
else if (property === "contents"){
@ -129,7 +151,7 @@ var DISCORD = (function(){
processed = processed
.replace(REGEX.formatUrl, "<a href='$1' target='_blank' rel='noreferrer'>$1</a>")
.replace(REGEX.mentionChannel, (full, match) => "<span class='link mention-chat'>#"+STATE.getChannelName(match)+"</span>")
.replace(REGEX.mentionUser, (full, match) => "<span class='link mention-user'>@"+STATE.getUserName(match)+"</span>")
.replace(REGEX.mentionUser, (full, match) => "<span class='link mention-user' title='#"+STATE.getUserTag(match)+"'>@"+STATE.getUserName(match)+"</span>")
.replace(REGEX.customEmojiStatic, "<img src='https://cdn.discordapp.com/emojis/$2.png' alt=':$1:' title=':$1:' class='emoji'>")
.replace(REGEX.customEmojiAnimated, "<img src='https://cdn.discordapp.com/emojis/$2."+animatedEmojiExtension+"' alt=':$1:' title=':$1:' class='emoji'>");

View File

@ -38,6 +38,7 @@ var GUI = (function(){
showModal(560, `
<label><input id='dht-cfg-imgpreviews' type='checkbox'> Image Previews</label><br>
<label><input id='dht-cfg-formatting' type='checkbox'> Message Formatting</label><br>
<label><input id='dht-cfg-useravatars' type='checkbox'> User Avatars</label><br>
<label><input id='dht-cfg-animemoji' type='checkbox'> Animated Emoji</label><br>`);
var setupCheckBox = function(id, settingName){
@ -48,6 +49,7 @@ var GUI = (function(){
setupCheckBox("dht-cfg-imgpreviews", "enableImagePreviews");
setupCheckBox("dht-cfg-formatting", "enableFormatting");
setupCheckBox("dht-cfg-useravatars", "enableUserAvatars");
setupCheckBox("dht-cfg-animemoji", "enableAnimatedEmoji");
};

View File

@ -35,6 +35,10 @@ class SAVEFILE{
return this.meta.users[this.meta.userindex[index]] || { "name": "&lt;unknown&gt;" };
}
getUserId(index){
return this.meta.userindex[index];
}
getUserById(user){
return this.meta.users[user] || { "name": user };
}

View File

@ -69,11 +69,15 @@ var STATE = (function(){
ROOT.getChannelName = function(channel){
return FILE.getChannelById(channel).name;
};
ROOT.getUserName = function(user){
return FILE.getUserById(user).name;
};
ROOT.getUserTag = function(user){
return FILE.getUserById(user).tag;
};
// --------------------------
// Channel list and selection
// --------------------------
@ -100,7 +104,10 @@ var STATE = (function(){
"id": key,
"name": channels[key].name,
"server": FILE.getServer(channels[key].server),
"msgcount": getFilteredMessageKeys(key).length
"msgcount": getFilteredMessageKeys(key).length,
"topic": channels[key].topic || "",
"nsfw": channels[key].nsfw || false,
"position": channels[key].position || -1
})).sort((ac, bc) => {
var as = ac.server;
var bs = bc.server;
@ -137,9 +144,12 @@ var STATE = (function(){
return MSGS.slice(startIndex, !messagesPerPage ? undefined : startIndex+messagesPerPage).map(key => {
var message = messages[key];
var user = FILE.getUser(message.u);
var avatar = user.avatar ? { id: FILE.getUserId(message.u), path: user.avatar } : null;
return {
"user": FILE.getUser(message.u),
"user": user,
"avatar": avatar,
"timestamp": message.t,
"contents": ("m" in message) ? message.m : null,
"embeds": message.e,
@ -327,6 +337,7 @@ var STATE = (function(){
defineSettingProperty("enableImagePreviews", true, fromBooleanString);
defineSettingProperty("enableFormatting", true, fromBooleanString);
defineSettingProperty("enableUserAvatars", true, fromBooleanString);
defineSettingProperty("enableAnimatedEmoji", true, fromBooleanString);
// End

View File

@ -31,7 +31,7 @@
overflow: hidden;
}
#channels .msgcount {
#channels .tag {
flex-shrink: 1;
background-color: rgba(255, 255, 255, 0.08);
border-radius: 4px;

View File

@ -16,6 +16,27 @@
display: block;
}
#messages .avatar-wrapper {
display: flex;
flex-direction: row;
align-items: flex-start;
align-content: flex-start;
}
#messages .avatar-wrapper > div {
flex: 1 1 auto;
}
#messages .avatar {
flex: 0 0 38px !important;
margin: 8px 14px 0 0;
}
#messages .avatar img {
width: 38px;
border-radius: 50%;
}
#messages .username {
color: #FFF;
font-size: 15px;