Skip to content

Commit 895e2bf

Browse files
authored
Handle required input types (#1059)
* Initial commit * Handle all input types * Fix info and label text * Misc * Verify that requiredInput has not changed * Submit input on enter key press * Show error if code is empty * Show info about required input as bot status
1 parent 0699264 commit 895e2bf

File tree

9 files changed

+195
-3
lines changed

9 files changed

+195
-3
lines changed

src/components/BotCard.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
<script>
2929
import { mapGetters } from 'vuex';
30+
import getUserInputType from '../utils/getUserInputType';
3031
3132
const quickActionButtons = [
3233
{ name: '2fa', icon: 'lock' },
@@ -44,6 +45,7 @@
4445
...mapGetters({
4546
nicknames: 'settings/nicknames',
4647
favButtons: 'settings/favButtons',
48+
headless: 'asf/headless',
4749
}),
4850
isPauseButtonSelected() {
4951
return this.selectedButtons.filter(e => e.name === 'pause').length > 0;
@@ -76,6 +78,13 @@
7678
},
7779
async start() {
7880
try {
81+
const inputType = getUserInputType(this.bot.requiredInput);
82+
83+
if (this.headless && inputType !== 'None') {
84+
this.$router.push({ name: 'bot-input', params: { bot: this.bot.name, type: inputType } });
85+
return;
86+
}
87+
7988
await this.$http.botAction(this.bot.name, 'start');
8089
await this.$store.dispatch('bots/updateBot', { name: this.bot.name, active: true });
8190
} catch (err) {

src/i18n/locale/default.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"bot-nicknames-description": "Display steam nicknames (if available) instead of bot names.",
4949
"bot-status-disabled": "Disabled",
5050
"bot-status-farming": "Farming",
51+
"bot-status-input": "Requires input",
5152
"bot-status-offline": "Offline",
5253
"bot-status-online": "Online",
5354
"bots": "Bots",
@@ -79,6 +80,23 @@
7980
"global-config": "Global Config",
8081
"info": "Info",
8182
"input-all-selected": "All values selected",
83+
"input-info-login": "You have not set a login name for this account.",
84+
"input-info-password": "You have not set a password for this account.",
85+
"input-info-steamguard": "This account is currently using Steam Guard.",
86+
"input-info-steamparentalcode": "This account is currently using Steam Family View.",
87+
"input-info-twofactorauthentication": "This account is currently using a Steam authenticator app.",
88+
"input-label-login": "Steam login name",
89+
"input-label-password": "Steam password",
90+
"input-label-steamguard": "Steam Guard code",
91+
"input-label-steamparentalcode": "Steam Parental code",
92+
"input-label-twofactorauthentication": "2FA code",
93+
"input-no-code-login": "You have to enter a Steam login name",
94+
"input-no-code-password": "You have to enter a Steam password",
95+
"input-no-code-steamguard": "You have to enter a Steam Guard code",
96+
"input-no-code-steamparentalcode": "You have to enter a Steam Parental code",
97+
"input-no-code-twofactorauthentication": "You have to enter a 2FA code",
98+
"input-submit": "Submit",
99+
"input-switch-visibility": "Switch input field visibility",
82100
"input-unknown-type": "Unknown field type",
83101
"keep-unchanged": "<keep unchanged>",
84102
"keys-copied": "Copied keys to clipboard!",

src/models/Bot.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export class Bot {
2020
this.walletBalance = data.WalletBalance;
2121
this.walletCurrency = data.WalletCurrency;
2222
this.has2FA = data.HasMobileAuthenticator;
23+
this.requiredInput = data.RequiredInput;
2324

2425
this.active = data.KeepRunning;
2526
this.config = data.BotConfig;
@@ -44,6 +45,7 @@ export class Bot {
4445

4546
if (this.status === 'farming' && this.currentGamesFarming.length === 1) return `${statusText} - ${this.currentGamesFarming[0].GameName}`;
4647
if (this.status === 'farming' && this.currentGamesFarming.length > 1) return `${statusText} - ${Vue.i18n.translate('multiple-games')}`;
48+
if (this.status === 'disabled' && this.requiredInput !== 0) return Vue.i18n.translate('bot-status-input');
4749

4850
return statusText;
4951
}

src/plugins/icons.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
faTimesCircle, faCheckCircle, faEdit, faTimes, faSquare, faMoon, faPalette, faPlay, faQuestion, faPlus,
77
faSpinner, faKey, faTrash, faCloudDownloadAlt, faSignOutAlt, faAngleDown, faLanguage, faGamepad, faClone,
88
faCalendarCheck, faLock, faBookOpen, faExclamation, faCodeBranch, faHourglassEnd, faHourglassHalf, faHourglassStart,
9-
faRedoAlt, faClipboard, faPuzzlePiece, faUndoAlt,
9+
faRedoAlt, faClipboard, faPuzzlePiece, faUndoAlt, faEye, faEyeSlash,
1010
} from '@fortawesome/free-solid-svg-icons';
1111

1212
import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/vue-fontawesome';
@@ -15,7 +15,7 @@ library.add(faWrench, faBars, faLaptop, faUsers, faFileAlt, faTachometerAlt, faP
1515
faClock, faTimesCircle, faCheckCircle, faEdit, faTimes, faSquare, faMoon, faPalette, faPlay, faQuestion,
1616
faPlus, faSpinner, faKey, faTrash, faCloudDownloadAlt, faSignOutAlt, faAngleDown, faLanguage, faGamepad,
1717
faClone, faCalendarCheck, faLock, faGithub, faBookOpen, faExclamation, faCodeBranch, faHourglassEnd, faHourglassHalf,
18-
faHourglassStart, faRedoAlt, faClipboard, faPuzzlePiece, faUndoAlt);
18+
faHourglassStart, faRedoAlt, faClipboard, faPuzzlePiece, faUndoAlt, faEye, faEyeSlash);
1919

2020
export default {
2121
install(Vue) {

src/router/routes.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ export default [
100100
modal: () => import('../views/modals/Bot2FA.vue')
101101
},
102102
meta: { modal: true }
103+
},
104+
{
105+
path: '/page/bot/:bot/input/:type',
106+
name: 'bot-input',
107+
components: {
108+
default: () => import('../views/Bots.vue'),
109+
modal: () => import('../views/modals/BotInput.vue')
110+
},
111+
meta: { modal: true }
103112
},
104113
{
105114
path: '/page/bot/:bot/delete',

src/store/modules/asf.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export const state = {
3131
uptime: '0s',
3232
updateChannel: 1,
3333
steamOwnerID: '0',
34+
headless: false,
3435
};
3536

3637
export const mutations = {
@@ -47,6 +48,7 @@ export const mutations = {
4748
},
4849
updateUpdateChannel: (state, updateChannel) => (state.updateChannel = updateChannel),
4950
updateSteamOwnerID: (state, steamOwnerID) => (state.steamOwnerID = steamOwnerID),
51+
updateHeadless: (state, headless) => (state.headless = headless),
5052
};
5153

5254
export const actions = {
@@ -69,6 +71,7 @@ export const actions = {
6971
commit('calculateUptime');
7072
commit('updateUpdateChannel', response.GlobalConfig.UpdateChannel);
7173
commit('updateSteamOwnerID', response.GlobalConfig.s_SteamOwnerID);
74+
commit('updateHeadless', response.GlobalConfig.Headless);
7275
} catch (err) {
7376
console.warn(err.message);
7477
}
@@ -87,4 +90,5 @@ export const getters = {
8790
startTime: state => state.startTime,
8891
updateChannel: state => state.updateChannel,
8992
steamOwnerID: state => state.steamOwnerID,
93+
headless: state => state.headless,
9094
};

src/utils/getUserInputType.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Todo: Read EUserInputType from api
2+
3+
const types = {
4+
None: 0,
5+
Login: 1,
6+
Password: 2,
7+
SteamGuard: 3,
8+
SteamParentalCode: 4,
9+
TwoFactorAuthentication: 5,
10+
};
11+
12+
export default function getUserInputType(id) {
13+
return Object.keys(types)[id];
14+
}

src/views/modals/Bot.vue

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,18 @@
5252
import BotFarmingInfo from '../../components/BotFarmingInfo.vue';
5353
import BotGames from '../../components/BotGames.vue';
5454
import BotLink from '../../components/BotLink.vue';
55+
import getUserInputType from '../../utils/getUserInputType';
5556
5657
export default {
5758
name: 'bot',
5859
components: {
5960
BotAction, BotFarmingInfo, BotGames, BotLink,
6061
},
6162
computed: {
62-
...mapGetters({ nicknames: 'settings/nicknames' }),
63+
...mapGetters({
64+
nicknames: 'settings/nicknames',
65+
headless: 'asf/headless',
66+
}),
6367
bot() {
6468
return this.$store.getters['bots/bot'](this.$route.params.bot);
6569
},
@@ -100,6 +104,13 @@
100104
await this.update({ paused: false });
101105
},
102106
async start() {
107+
const inputType = getUserInputType(this.bot.requiredInput);
108+
109+
if (this.headless && inputType !== 'None') {
110+
this.$router.push({ name: 'bot-input', params: { bot: this.bot.name, type: inputType } });
111+
return;
112+
}
113+
103114
await this.action('start');
104115
await this.update({ active: true });
105116
},

src/views/modals/BotInput.vue

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<template>
2+
<main v-if="bot" class="main-container">
3+
<h2 v-if="bot.nickname && nicknames" class="title">{{ bot.nickname }}</h2>
4+
<h2 v-else class="title">{{ bot.name }}</h2>
5+
6+
<div class="form-item">
7+
<div class="form-item__info">{{ $t(`input-info-${inputType}`) }}</div>
8+
<div class="form-item__code">
9+
<div>
10+
<label for="input" class="form-item__label">{{ $t(`input-label-${inputType}`) }}</label>
11+
<input id="input" class="form-item__input" type="password" autocomplete="new-password" v-model="code" />
12+
</div>
13+
<div class="form-item__buttons form-item__buttons--column">
14+
<button class="button button--helper" :title="$t('input-switch-visibility')" @click="switchInputType">
15+
<font-awesome-icon v-if="inputHidden" icon="eye" size="lg"></font-awesome-icon>
16+
<font-awesome-icon v-else icon="eye-slash" size="lg"></font-awesome-icon>
17+
</button>
18+
</div>
19+
</div>
20+
<div class="form-item__buttons form-item__buttons--center">
21+
<button class="button button--confirm" @click="submit">
22+
<font-awesome-icon v-if="submitting" icon="spinner" spin></font-awesome-icon>
23+
<span v-else>{{ $t('input-submit') }}</span>
24+
</button>
25+
</div>
26+
</div>
27+
</main>
28+
</template>
29+
30+
<script>
31+
import { mapGetters } from 'vuex';
32+
import getUserInputType from '../../utils/getUserInputType';
33+
34+
export default {
35+
name: 'bot-input',
36+
data() {
37+
return {
38+
submitting: false,
39+
code: '',
40+
inputHidden: true,
41+
};
42+
},
43+
computed: {
44+
...mapGetters({ nicknames: 'settings/nicknames' }),
45+
bot() {
46+
return this.$store.getters['bots/bot'](this.$route.params.bot);
47+
},
48+
inputType() {
49+
return this.$route.params.type.toLowerCase();
50+
},
51+
},
52+
created() {
53+
if (!this.bot || !this.$route.params.type) this.$router.replace({ name: 'bots' });
54+
document.addEventListener('keydown', this.onEnterClick);
55+
},
56+
beforeDestroy() {
57+
document.removeEventListener('keydown', this.onEnterClick);
58+
},
59+
mounted() {
60+
document.getElementById('input').focus();
61+
},
62+
methods: {
63+
switchInputType() {
64+
this.inputHidden = !this.inputHidden;
65+
const field = document.getElementById('input');
66+
67+
if (field.getAttribute('type') === 'password') field.setAttribute('type', 'text');
68+
else field.setAttribute('type', 'password');
69+
},
70+
onEnterClick(e) {
71+
const charCode = (e.which) ? e.which : e.keyCode;
72+
73+
if (charCode === 13) {
74+
this.submit();
75+
return e.preventDefault();
76+
}
77+
},
78+
async submit() {
79+
if (this.submitting) return;
80+
81+
if (this.code === '') {
82+
this.$error(this.$t(`input-no-code-${this.inputType}`));
83+
return;
84+
}
85+
86+
this.submitting = true;
87+
88+
try {
89+
const inputType = getUserInputType(this.bot.requiredInput);
90+
if (inputType === this.$route.params.type) await this.$http.post(`bot/${this.bot.name}/input`, { type: this.bot.requiredInput, value: this.code });
91+
await this.$http.botAction(this.bot.name, 'start');
92+
await this.$store.dispatch('bots/updateBot', { name: this.bot.name, active: true });
93+
94+
this.$router.back();
95+
} catch (err) {
96+
this.$error(err.message);
97+
} finally {
98+
this.submitting = false;
99+
}
100+
},
101+
},
102+
};
103+
</script>
104+
105+
<style lang="scss">
106+
.form-item__info {
107+
padding-bottom: 1em;
108+
}
109+
110+
.form-item__code {
111+
display: grid;
112+
grid-column-gap: 0.5em;
113+
grid-template-columns: 1fr auto;
114+
align-items: flex-end;
115+
padding-bottom: 1em;
116+
117+
:focus {
118+
outline: none;
119+
}
120+
}
121+
122+
.button--helper {
123+
max-width: 2em;
124+
}
125+
</style>

0 commit comments

Comments
 (0)