First rewrite release

This commit is contained in:
2022-10-31 21:57:20 +07:00
parent c55d79ae35
commit e2f419e0d9
2 changed files with 611 additions and 0 deletions

View File

@@ -0,0 +1,250 @@
{
"info": {
"name": "UrgentNotification",
"authors": [
{
"name": "YuzuZensai",
"discord_id": "",
"github_username": "YuzuZensai",
"twitter_username": "YuzuZensai"
}
],
"version": "0.0.2",
"description": "Allow urgent messages to bypass do not disturb mode, streamer mode and others.",
"github": "",
"github_raw": ""
},
"changelog": [],
"defaultConfig": [
{
"type": "textbox",
"id": "triggerCommand",
"name": "Trigger command",
"note": "Trigger command for the urgent notification",
"value": "!urgent"
},
{
"type": "switch",
"id": "commandResponseEnabled",
"name": "💬 Enable urgent command reply",
"note": "The plugin will send a confirmation message when the urgent command is triggered back to the user",
"value": true
},
{
"type": "switch",
"id": "autoReplyEnabled",
"name": "✉️ Enable AutoReply",
"note": "When a new message is received, the plugin will automatically reply with information about current status and how to trigger the urgent notification",
"value": true
},
{
"type": "switch",
"id": "onlyFromFriends",
"name": "🧑‍🤝‍🧑 Friends only mode",
"note": "Only reply back and allow urgent notifications from friends",
"value": true
},
{
"type": "category",
"id": "timer",
"name": "⌛ Timer",
"collapsible": true,
"shown": false,
"settings": [
{
"type": "slider",
"id": "commandResponseCooldown",
"name": "Urgent command cooldown",
"note": "How long until the user can trigger the urgent command again (in minutes)",
"value": 5,
"min": 1,
"max": 120,
"markers": [1, 5, 10, 15, 20, 30, 60, 90, 120],
"stickToMarkers": true
},
{
"type": "slider",
"id": "autoReplyCooldown",
"name": "AutoReply cooldown",
"note": "How long until AutoReply can be triggered again (in minutes)",
"value": 30,
"min": 5,
"max": 120,
"markers": [5, 10, 15, 20, 30, 60, 90, 120],
"stickToMarkers": true
},
{
"type": "slider",
"id": "autoReplySelfDeleteCountdown",
"name": "AutoReply Self Delete Countdown",
"note": "How long until AutoReply will self delete the message (in minutes)",
"value": 5,
"min": 1,
"max": 120,
"markers": [1, 5, 10, 15, 20, 30, 60, 90, 120],
"stickToMarkers": true
}
]
},
{
"type": "category",
"id": "commandResponseMessage",
"name": "✏️ Customize command response message",
"collapsible": true,
"shown": false,
"settings": [
{
"type": "textbox",
"id": "header",
"name": "Header",
"note": "",
"value": "❗✉️ㅤ**__URGENT NOTIFICATION SENT__**"
},
{
"type": "textbox",
"id": "body",
"name": "Body",
"note": "",
"value": "If I'm taking too long to respond, please send send ``!urgent`` again (there is a cooldown)\\nPlease don't abuse the urgent tag. Thanks you"
}
]
},
{
"type": "category",
"id": "streaming",
"name": "🔴 [AutoReply] When streaming",
"collapsible": true,
"shown": false,
"settings": [
{
"type": "switch",
"id": "enabled",
"name": "Enable",
"note": "",
"value": true
},
{
"type": "textbox",
"id": "header",
"name": "Header",
"note": "",
"value": "🌙ㅤ**${username} has notifications silenced**"
},
{
"type": "textbox",
"id": "body",
"name": "Body",
"note": "",
"value": "🔴I'm currently streaming or recording, in order to prevent any accidental notifications being shown\\n and other reasons. I'll check my notifications periodically."
}
]
},
{
"type": "category",
"id": "dnd",
"name": "🔕 [AutoReply] When do not disturb enabled",
"collapsible": true,
"shown": false,
"settings": [
{
"type": "switch",
"id": "enabled",
"name": "Enable",
"note": "",
"value": true
},
{
"type": "textbox",
"id": "header",
"name": "Header",
"note": "",
"value": "🌙ㅤ**${username} has notifications silenced**"
},
{
"type": "textbox",
"id": "body",
"name": "Body",
"note": "",
"value": "🔕I'm currently busy, I'll respond to you later."
}
]
},
{
"type": "category",
"id": "idle",
"name": "🌙 [AutoReply] Idle",
"collapsible": true,
"shown": false,
"settings": [
{
"type": "switch",
"id": "enabled",
"name": "Enable",
"note": "",
"value": true
},
{
"type": "textbox",
"id": "header",
"name": "Header",
"note": "",
"value": "🌙ㅤ**${username} is currently away**"
},
{
"type": "textbox",
"id": "body",
"name": "Body",
"note": "",
"value": "💤I'm currently AFK right now, doing things in real life, or just taking a break."
}
]
},
{
"type": "category",
"id": "inVR",
"name": "🥽 [AutoReply] When using VR headset",
"collapsible": true,
"shown": false,
"settings": [
{
"type": "switch",
"id": "enabled",
"name": "Enable",
"note": "",
"value": true
},
{
"type": "textbox",
"id": "header",
"name": "Header",
"note": "",
"value": "🥽ㅤ**${username} is currently in VR**"
},
{
"type": "textbox",
"id": "body",
"name": "Body",
"note": "",
"value": " 👁🗨I'm currently wearing a VR headset. I might not be able to respond to you right away\\n I'll check my notifications periodically."
}
]
},
{
"type": "category",
"id": "general",
"name": "✉️ [AutoReply] Footer text",
"collapsible": true,
"shown": false,
"settings": [
{
"type": "textbox",
"id": "footer",
"name": "Footer text",
"note": "",
"value": "⚠If this is an urgent matter or need to contact me ASAP, please send ``!urgent``."
}
]
}
],
"main": "index.js"
}

View File

@@ -0,0 +1,361 @@
/**
*
* @param {import("zerespluginlibrary").Plugin} Plugin
* @param {import("zerespluginlibrary").BoundAPI} Library
* @returns
*/
module.exports = (Plugin, Library) => {
const { DiscordModules, Logger } = Library;
const {
UserStore,
ChannelStore,
MessageStore,
RelationshipStore,
UserStatusStore,
StreamerModeStore,
Dispatcher,
MessageQueue,
APIModule,
MessageActions,
NavigationUtils,
NotificationModule,
} = DiscordModules;
return class extends Plugin {
onStart() {
Logger.info("Plugin enabled!");
Dispatcher.subscribe("MESSAGE_CREATE", this.onMessage.bind(this));
if (!global.UrgentNotification)
global.UrgentNotification = {
recently_sent: [],
cooldown: [],
resetCooldowns: () => {
global.UrgentNotification.recently_sent = [];
global.UrgentNotification.cooldown = [];
Logger.info("Recently sent and cooldown list cleared");
},
resetAll: () => {
global.UrgentNotification.resetCooldowns();
global.UrgentNotification.purgePendingDeleteNow();
},
purgePendingDeleteNow: () => {
Logger.info("Pending delete messages cleared");
for (let x in global.UrgentNotification.pending_delete) {
clearTimeout(x);
global.UrgentNotification.pending_delete[x].f();
}
global.UrgentNotification.pending_delete = {};
},
};
if (!global.UrgentNotification.cooldown)
global.UrgentNotification.cooldown = [];
if (!global.UrgentNotification.recently_sent)
global.UrgentNotification.recently_sent = [];
if (!global.UrgentNotification.pending_delete)
global.UrgentNotification.pending_delete = {};
}
onStop() {
Dispatcher.unsubscribe("MESSAGE_CREATE", this.onMessage.bind(this));
Logger.info("Plugin disabled!");
}
getSettings() {
return this.settings;
}
onMessage(data) {
let channel = ChannelStore.getChannel(data.channelId);
let isGuild = channel.guild_id != null;
let isDM = channel.type == 1;
if (isGuild || !isDM || !data.message) return;
let message = data.message;
let isNormalMessage = message.type == 0;
if (!isNormalMessage) return;
if (!message.author)
message = MessageStore.getMessage(channel.id, message.id);
if (!message.author) return;
let author = message.author;
if (author.id === this.getUserID()) return;
let isFriend = RelationshipStore.isFriend(message.author.id);
let streamerModeSettings = StreamerModeStore.getSettings();
let status = UserStatusStore.getStatus(this.getUserID());
let isStreamerModeEnabled =
streamerModeSettings.enabled || status === "streaming";
let activities = UserStatusStore.getActivities(this.getUserID());
let isVR = activities.some((x) => x.name === "SteamVR");
if (status === "invisible") return;
if (status === "online" && !isStreamerModeEnabled && !isVR) return;
//if (status === "idle") return;
if (message.content === this.settings.triggerCommand) {
if (this.settings.onlyFromFriends && !isFriend) {
Logger.info(
message.author.username,
"is not your friend, urgent message ignored"
);
return;
}
let isCooldown = global.UrgentNotification.cooldown.includes(author.id);
if (isCooldown) return;
global.UrgentNotification.cooldown.push(author.id);
Logger.info("Added", author.username, "to cooldown list");
setTimeout(() => {
global.UrgentNotification.cooldown =
global.UrgentNotification.cooldown.filter((e) => e !== author.id);
Logger.info("Removed from cooldown", message.author.username);
}, this.getCommandResponseCooldown());
this.forceNotify(channel, message);
if (!this.settings.commandResponseEnabled) return;
MessageQueue.enqueue(
{
type: 0,
message: {
channelId: channel.id,
content: this.makeCommandResponseMessage(
{ username: this.getLocalUsername() },
this.settings
),
tts: false,
},
},
(data) => {
Logger.info("Message sent to", message.author.username);
let newMessage = data.body;
this.scheduleDelete(
channel.id,
newMessage.id,
this.getAutoReplySelfDeleteCountdown()
);
this.sendACK(channel.id, message.id, 2);
}
);
} else {
if (!this.settings.autoReplyEnabled) return;
if (this.settings.onlyFromFriends && !isFriend) return;
let isRecentlySent = global.UrgentNotification.recently_sent.includes(
author.id
);
if (isRecentlySent) return;
let isCooldown = global.UrgentNotification.cooldown.includes(author.id);
if (isCooldown) return;
let messageToSend;
if (this.settings.streaming.enabled && isStreamerModeEnabled)
messageToSend = this.makeStreamingMessage(
{ username: this.getLocalUsername() },
this.settings
);
else if (this.settings.dnd.enabled && status === "dnd")
messageToSend = this.makeDNDMessage(
{ username: this.getLocalUsername() },
this.settings
);
else if (this.settings.inVR.enabled && isVR)
messageToSend = this.makeInVRMessage(
{ username: this.getLocalUsername() },
this.settings
);
else if (this.settings.idle.enabled && status === "idle")
messageToSend = this.makeIdleMessage(
{ username: this.getLocalUsername() },
this.settings
);
else return;
global.UrgentNotification.recently_sent.push(author.id);
Logger.info("Added", author.username, "to recently sent list");
setTimeout(() => {
global.UrgentNotification.recently_sent =
global.UrgentNotification.recently_sent.filter(
(e) => e !== author.id
);
Logger.info("Removed from recently sent", message.author.username);
}, this.getAutoReplyCooldown());
MessageQueue.enqueue(
{
type: 0,
message: {
channelId: channel.id,
content: messageToSend,
tts: false,
},
},
(data) => {
Logger.info("Message sent to", message.author.username);
let newMessage = data.body;
this.scheduleDelete(
channel.id,
newMessage.id,
this.getAutoReplySelfDeleteCountdown()
);
this.sendACK(channel.id, message.id, 2);
}
);
}
}
getSettingsPanel() {
return this.buildSettingsPanel().getElement();
}
makeStreamingMessage(data, settings) {
return this.makeMessage(
data,
settings.streaming.header,
settings.streaming.body,
settings.general.footer
);
}
makeDNDMessage(data, settings) {
return this.makeMessage(
data,
settings.dnd.header,
settings.dnd.body,
settings.general.footer
);
}
makeIdleMessage(data, settings) {
return this.makeMessage(
data,
settings.idle.header,
settings.idle.body,
settings.general.footer
);
}
makeInVRMessage(data, settings) {
return this.makeMessage(
data,
settings.inVR.header,
settings.inVR.body,
settings.general.footer
);
}
makeFancyMessage(text) {
text = text.replaceAll("\n", "\n> ");
text = text.replaceAll("\\n", "\n> ");
if (text.charAt(text.length - 1) == " ") {
text = text.substring(0, text.length - 1) + " \n";
}
return `> ${text}`;
}
makeCommandResponseMessage(data, settings) {
return this.makeFancyMessage(
`\n${settings.commandResponseMessage.header.replaceAll(
"${username}",
data.username
)}\n\n${settings.commandResponseMessage.body.replaceAll(
"${username}",
data.username
)}\n`
);
}
makeMessage(data, header, body, footer) {
return this.makeFancyMessage(
`\n${header.replaceAll(
"${username}",
data.username
)}\n\n${body.replaceAll(
"${username}",
data.username
)}\n\n${footer.replaceAll("${username}", data.username)}\n`
);
}
forceNotify(channel, message) {
NotificationModule.showNotification(
`https://cdn.discordapp.com/avatars/${message.author.id}/${message.author.avatar}.webp?size=96`,
`[URGENT] Notification`,
`from ${message.author.username}`,
{
notif_type: "MESSAGE_CREATE",
notif_user_id: message.author.id,
message_id: message.id,
message_type: message.type,
channel_id: channel.id,
channel_type: channel.type,
guild_id: null,
},
{
omitViewTracking: true,
overrideStreamerMode: true,
sound: "message1",
volume: 0.4,
onClick: () => {
NavigationUtils.transitionTo(
`/channels/@me/${channel.id}/${message.id}`,
undefined,
undefined
);
},
}
);
}
sendACK(channelID, messageID, count) {
APIModule.post({
url: `/channels/${channelID}/messages/${messageID}/ack`,
body: {
manual: true,
mention_count: count,
},
});
}
scheduleDelete(channelID, messageID, timeout) {
const f = () => {
MessageActions.deleteMessage(channelID, messageID);
delete global.UrgentNotification.pending_delete[x];
};
let x = setTimeout(f, timeout);
global.UrgentNotification.pending_delete[x] = { channelID, messageID, f };
}
getAutoReplySelfDeleteCountdown() {
return this.settings.timer.autoReplySelfDeleteCountdown * 60 * 1000;
}
getCommandResponseCooldown() {
return this.settings.timer.commandResponseCooldown * 60 * 1000;
}
getAutoReplyCooldown() {
return this.settings.timer.autoReplyCooldown * 60 * 1000;
}
getUserID() {
return UserStore.getCurrentUser().id;
}
getLocalUsername() {
return UserStore.getCurrentUser().username;
}
};
};