Skip to content

feat: Smart Switch Auto On/Off on a timer #289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docs/smart_devices.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ It is possible to change the display image for all the different Smart Devices b

The image above is what a paired Smart Switch looks like in Discord. In this case the Smart Switch is called `Switch` and is located at E16. All Smart Devices have an Entity Id which is used to identify it. The Custom Command for this switch is `!sw` which can be used from the in-game teamchat.
<br><br>
The Smart Switch can be turned ON/OFF by clicking the `TURN ON` / `TURN OFF` button at the bottom. By clicking on the `EDIT` button, you can edit things such as the `Name` and the `Custom Command` for the Smart Switch. If the `AUTO SETTING` is set to either `AUTO-ON-PROXIMITY` or `AUTO-OFF-PROXIMITY`, there will be a proximity setting available to edit. The proximity setting is used to turn the switch ON/OFF when a teammate is within the proximity of the Smart Switch. To remove the Smart Switch, just click the trashcan button.
The Smart Switch can be turned ON/OFF by clicking the `TURN ON` / `TURN OFF` button at the bottom. By clicking on the `EDIT` button, you can edit things such as the `Name` and the `Custom Command` for the Smart Switch.
If the `AUTO SETTING` is set to either `AUTO-ON-PROXIMITY` or `AUTO-OFF-PROXIMITY`, there will be a proximity setting available to edit. The proximity setting is used to turn the switch ON/OFF when a teammate is within the proximity of the Smart Switch. To remove the Smart Switch, just click the trashcan button.
If the `AUTO SETTING` is set to either `AUTO-ON-TIMER` or `AUTO-OFF-TIMER`, there will be a timer setting available to edit. The timer setting is used to turn the switch ON/OFF after the specified delay.
To remove the Smart Switch, just click the trashcan button.
<br><br>
There are a few auto settings for Smart Switches:
- **OFF** - Smart Switch work as normal.
Expand All @@ -25,6 +28,8 @@ There are a few auto settings for Smart Switches:
- **AUTO-OFF-PROXIMITY** - Smart Switch will automatically go inactive if teammate is in proximity, if outside proximity it will go active.
- **AUTO-ON-ANY-ONLINE** - Smart Switch will automatically go active if any teammate is online, if all offline it will go inactive.
- **AUTO-OFF-ANY-ONLINE** - Smart Switch will automatically go inactive if any teammate is online, if all offline it will go active.
- **AUTO-ON-TIMER** - Smart Switch will automatically go active after specified delay.
- **AUTO-OFF-TIMER** - Smart Switch will automatically go inactive after specified delay.

<br>

Expand Down
11 changes: 11 additions & 0 deletions src/discordTools/discordModals.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,17 @@ module.exports = {
);
}

if (entity.autoDayNightOnOff === 9 || entity.autoDayNightOnOff === 10) {
modal.addComponents(
new Discord.ActionRowBuilder().addComponents(TextInput.getTextInput({
customId: 'SmartSwitchOnOffTimer',
label: Client.client.intlGet(guildId, 'smartSwitchEditOnOffTimerLabel'),
value: `${entity.onOffTimer}`,
style: Discord.TextInputStyle.Short
}))
);
}

return modal;
},

Expand Down
14 changes: 14 additions & 0 deletions src/discordTools/discordSelectMenus.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ module.exports = {
const autoOffProximity = Client.client.intlGet(guildId, 'autoOffProximityCap');
const autoOnAnyOnline = Client.client.intlGet(guildId, 'autoOnAnyOnlineCap');
const autoOffAnyOnline = Client.client.intlGet(guildId, 'autoOffAnyOnlineCap');
const autoOnTimer = Client.client.intlGet(guildId, 'autoOnTimerCap');
const autoOffTimer = Client.client.intlGet(guildId, 'autoOffTimerCap');

let autoDayNightOnOffString = autoSetting;
if (entity.autoDayNightOnOff === 0) autoDayNightOnOffString += off;
Expand All @@ -245,6 +247,8 @@ module.exports = {
else if (entity.autoDayNightOnOff === 6) autoDayNightOnOffString += autoOffProximity;
else if (entity.autoDayNightOnOff === 7) autoDayNightOnOffString += autoOnAnyOnline;
else if (entity.autoDayNightOnOff === 8) autoDayNightOnOffString += autoOffAnyOnline;
else if (entity.autoDayNightOnOff === 9) autoDayNightOnOffString += autoOnTimer;
else if (entity.autoDayNightOnOff === 10) autoDayNightOnOffString += autoOffTimer;

return new Discord.ActionRowBuilder().addComponents(
module.exports.getSelectMenu({
Expand Down Expand Up @@ -295,6 +299,16 @@ module.exports = {
label: autoOffAnyOnline,
description: Client.client.intlGet(guildId, 'smartSwitchAutoOffAnyOnline'),
value: '8'
},
{
label: autoOnTimer,
description: Client.client.intlGet(guildId, 'smartSwitchAutoOnTimer'),
value: '9'
},
{
label: autoOffTimer,
description: Client.client.intlGet(guildId, 'smartSwitchAutoOffTimer'),
value: '10'
}]
}));
},
Expand Down
11 changes: 11 additions & 0 deletions src/handlers/modalHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ module.exports = async (client, interaction) => {
catch (e) {
smartSwitchProximity = null;
}
let smartSwitchOnOffTimer = null;
try {
smartSwitchOnOffTimer = interaction.fields.getTextInputValue('SmartSwitchOnOffTimer');;;
}
catch (e) {
smartSwitchOnOffTimer = null;
}

if (!server || (server && !server.switches.hasOwnProperty(ids.entityId))) {
interaction.deferUpdate();
Expand All @@ -130,6 +137,10 @@ module.exports = async (client, interaction) => {
if (smartSwitchProximity !== null && smartSwitchProximity >= 0) {
server.switches[ids.entityId].proximity = smartSwitchProximity;
}

if (smartSwitchOnOffTimer) {
server.switches[ids.entityId].onOffTimer = smartSwitchOnOffTimer;
}
client.setInstance(guildId, instance);

client.log(client.intlGet(null, 'infoCap'), client.intlGet(null, 'modalValueChange', {
Expand Down
72 changes: 72 additions & 0 deletions src/handlers/smartSwitchHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,78 @@ module.exports = {
changedSwitches.push(entityId);
}
}
else if (content.autoDayNightOnOff === 9) { /* AUTO-ON-TIMER */
let shouldBeOn = true;
const timeSeconds = Timer.getSecondsFromStringTime(content.onOffTimer);

if (!rustplus.currentSwitchTimeouts.hasOwnProperty(entityId) && ((shouldBeOn && !content.active) || (!shouldBeOn && content.active))) {
rustplus.currentSwitchTimeouts[entityId] = setTimeout(async function () {
instance.serverList[serverId].switches[entityId].active = shouldBeOn;
client.setInstance(guildId, instance);

rustplus.interactionSwitches.push(entityId);

const response = await rustplus.turnSmartSwitchAsync(entityId, shouldBeOn);
if (!(await rustplus.isResponseValid(response))) {
if (instance.serverList[serverId].switches[entityId].reachable) {
await DiscordMessages.sendSmartSwitchNotFoundMessage(guildId, serverId, entityId);
}
instance.serverList[serverId].switches[entityId].reachable = false;

rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== entityId);
}
else {
instance.serverList[serverId].switches[entityId].reachable = true;
}
client.setInstance(guildId, instance);

DiscordMessages.sendSmartSwitchMessage(guildId, serverId, entityId);
changedSwitches.push(entityId);
const str = client.intlGet(guildId, 'automaticallyTurningBackOnOff', {
device: instance.serverList[serverId].switches[entityId].name,
status: client.intlGet(guildId, 'onCap')
});

rustplus.sendInGameMessage(str);
}, timeSeconds * 1000);
}
}
else if (content.autoDayNightOnOff === 10) { /* AUTO-OFF-TIMER */
let shouldBeOn = false;
const timeSeconds = Timer.getSecondsFromStringTime(content.onOffTimer);

if (!rustplus.currentSwitchTimeouts.hasOwnProperty(entityId) && ((shouldBeOn && !content.active) || (!shouldBeOn && content.active))) {
rustplus.currentSwitchTimeouts[entityId] = setTimeout(async function () {
instance.serverList[serverId].switches[entityId].active = shouldBeOn;
client.setInstance(guildId, instance);

rustplus.interactionSwitches.push(entityId);

const response = await rustplus.turnSmartSwitchAsync(entityId, shouldBeOn);
if (!(await rustplus.isResponseValid(response))) {
if (instance.serverList[serverId].switches[entityId].reachable) {
await DiscordMessages.sendSmartSwitchNotFoundMessage(guildId, serverId, entityId);
}
instance.serverList[serverId].switches[entityId].reachable = false;

rustplus.interactionSwitches = rustplus.interactionSwitches.filter(e => e !== entityId);
}
else {
instance.serverList[serverId].switches[entityId].reachable = true;
}
client.setInstance(guildId, instance);

DiscordMessages.sendSmartSwitchMessage(guildId, serverId, entityId);
changedSwitches.push(entityId);
const str = client.intlGet(guildId, 'automaticallyTurningBackOnOff', {
device: instance.serverList[serverId].switches[entityId].name,
status: client.intlGet(guildId, 'offCap')
});

rustplus.sendInGameMessage(str);
}, timeSeconds * 1000);
}
}
}

let groupsId = SmartSwitchGroupHandler.getGroupsFromSwitchList(
Expand Down
5 changes: 5 additions & 0 deletions src/languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@
"autoOffAnyOnlineCap": "AUTO-OFF-ANY-ONLINE",
"autoOffCap": "AUTO-OFF",
"autoOffProximityCap": "AUTO-OFF-PROXIMITY",
"autoOffTimerCap": "AUTO-OFF-TIMER",
"autoOnAnyOnlineCap": "AUTO-ON-ANY-ONLINE",
"autoOnCap": "AUTO-ON",
"autoOnProximityCap": "AUTO-ON-PROXIMITY",
"autoOnTimerCap": "AUTO-ON-TIMER",
"autoSettingCap": "AUTO SETTING: ",
"automaticallyTurnBackOnOff": " Automatically turned back {status} in {time}.",
"automaticallyTurningBackOnOff": "Automatically turning {device} back {status}.",
Expand Down Expand Up @@ -647,9 +649,12 @@
"smartSwitchAutoOff": "Smart Switch will automatically go inactive during update cycle.",
"smartSwitchAutoOffAnyOnline": "Smart Switch will automatically go inactive if any teammate is online.",
"smartSwitchAutoOffProximity": "Smart Switch will automatically go inactive if teammate is in proximity.",
"smartSwitchAutoOffTimer": "Smart Switch will automatically go inactive after specified delay.",
"smartSwitchEditOnOffTimerLabel": "On/Off Timer Settings",
"smartSwitchAutoOn": "Smart Switch will automatically go active during update cycle.",
"smartSwitchAutoOnAnyOnline": "Smart Switch will automatically go active if any teammate is online.",
"smartSwitchAutoOnProximity": "Smart Switch will automatically go active if teammate is in proximity.",
"smartSwitchAutoOnTimer": "Smart Switch will automatically go active after specified delay.",
"smartSwitchEditProximityLabel": "Proximity Setting (meters):",
"smartSwitchEditSuccess": "Successfully edited Smart Switch {name}.",
"smartSwitchNormal": "Smart Switch work as normal.",
Expand Down
1 change: 1 addition & 0 deletions src/util/FcmListener.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ async function pairingEntitySwitch(client, guild, full, data, body) {
command: entityExist ? switches[body.entityId].command : body.entityId,
image: entityExist ? switches[body.entityId].image : 'smart_switch.png',
autoDayNightOnOff: entityExist ? switches[body.entityId].autoDayNightOnOff : 0,
onOffTimer: entityExist ? switches[body.entityId].onOffTimer : Constants.ON_OFF_TIMER_SETTING_DEFAULT_TIME,
location: entityExist ? switches[body.entityId].location : null,
x: entityExist ? switches[body.entityId].x : null,
y: entityExist ? switches[body.entityId].y : null,
Expand Down
1 change: 1 addition & 0 deletions src/util/FcmListenerLite.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ async function pairingEntitySwitch(client, guild, full, data, body) {
command: entityExist ? switches[body.entityId].command : body.entityId,
image: entityExist ? switches[body.entityId].image : 'smart_switch.png',
autoDayNightOnOff: entityExist ? switches[body.entityId].autoDayNightOnOff : 0,
onOffTimer: entityExist ? switches[body.entityId].onOffTimer : Constants.ON_OFF_TIMER_SETTING_DEFAULT_TIME,
location: entityExist ? switches[body.entityId].location : null,
x: entityExist ? switches[body.entityId].x : null,
y: entityExist ? switches[body.entityId].y : null,
Expand Down
1 change: 1 addition & 0 deletions src/util/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ module.exports = {
PATROL_HELI_DOWNED_RADIUS: 400,
OIL_RIG_CHINOOK_47_MAX_SPAWN_DISTANCE: 550,
PROXIMITY_SETTING_DEFAULT_METERS: 500,
ON_OFF_TIMER_SETTING_DEFAULT_TIME: '60s',

/* Emojis */
ONLINE_EMOJI: ':green_circle:',
Expand Down