Compare commits
1 commit
master
...
feature-te
Author | SHA1 | Date | |
---|---|---|---|
![]() |
71d1794d56 |
16 changed files with 219 additions and 105 deletions
|
@ -13,6 +13,12 @@ class HomeController extends Controller
|
|||
|
||||
public function submit($command)
|
||||
{
|
||||
if(request()->header('Accept') !== 'application/json')
|
||||
{
|
||||
return redirect()->to('/#'.$command);
|
||||
}
|
||||
|
||||
return (new CommandChain())->perform(strtolower($command));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,9 +15,7 @@ class CommandChain
|
|||
protected $commands = [
|
||||
Manual::class,
|
||||
Localhost::class,
|
||||
Clear::class,
|
||||
Ip::class,
|
||||
Doom::class,
|
||||
DnsLookup::class,
|
||||
];
|
||||
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Commands\Commands;
|
||||
|
||||
use App\Services\Commands\Command;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class Clear implements Command
|
||||
{
|
||||
public function canPerform(string $command): bool
|
||||
{
|
||||
return $command === 'clear';
|
||||
}
|
||||
|
||||
public function perform(string $command): Response
|
||||
{
|
||||
return redirect('/');
|
||||
}
|
||||
}
|
|
@ -24,11 +24,15 @@ class DnsLookup implements Command
|
|||
|
||||
$errorText = __('errors.noDnsRecordsFound', compact('domain'));
|
||||
|
||||
flash()->error($errorText);
|
||||
|
||||
return redirect('/');
|
||||
return response([
|
||||
'message' => $errorText,
|
||||
'type' => 'danger',
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->view('home.index', ['output' => htmlentities($dnsRecords)]);
|
||||
return response([
|
||||
'message' => htmlentities($dnsRecords),
|
||||
'type' => 'default',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\Commands\Commands;
|
||||
|
||||
use App\Services\Commands\Command;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class Doom implements Command
|
||||
{
|
||||
public function canPerform(string $command): bool
|
||||
{
|
||||
return $command === 'doom';
|
||||
}
|
||||
|
||||
public function perform(string $command): Response
|
||||
{
|
||||
return redirect('https://js-dos.com/games/doom.exe.html');
|
||||
}
|
||||
}
|
|
@ -14,8 +14,9 @@ class Ip implements Command
|
|||
|
||||
public function perform(string $command): Response
|
||||
{
|
||||
$output = 'Your ip address is ' . request()->ip() . '.';
|
||||
|
||||
return response()->view('home.index', ['output'=> $output]);
|
||||
return response([
|
||||
'message' => 'Your ip address is ' . request()->ip() . '.',
|
||||
'type' => 'default',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,9 @@ class Localhost implements Command
|
|||
|
||||
public function perform(string $command): Response
|
||||
{
|
||||
flash()->error("Please try someone else's domain.");
|
||||
|
||||
return back();
|
||||
return response([
|
||||
'message' => 'Please try someone else\'s domain.',
|
||||
'type' => 'danger',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,9 @@ class Manual implements Command
|
|||
"Enter 'doom' to play Doom.",
|
||||
])->implode('<br>');
|
||||
|
||||
flash()->message($manualText, 'info');
|
||||
|
||||
return redirect('/');
|
||||
return response([
|
||||
'message' => $manualText,
|
||||
'type' => 'info'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
1
resources/assets/css/base/headings.css
vendored
1
resources/assets/css/base/headings.css
vendored
|
@ -1,5 +1,6 @@
|
|||
h1 {
|
||||
font-size: 1rem;
|
||||
padding-top: 2rem;
|
||||
}
|
||||
|
||||
.h1__prefix {
|
||||
|
|
49
resources/assets/js/History.js
vendored
Normal file
49
resources/assets/js/History.js
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
class History {
|
||||
|
||||
constructor() {
|
||||
this.importFromLocalStorage();
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
add(value) {
|
||||
|
||||
if (this.items.length > 1000) {
|
||||
this.items.pop();
|
||||
}
|
||||
|
||||
this.items.unshift(value);
|
||||
this.save();
|
||||
}
|
||||
|
||||
importFromLocalStorage() {
|
||||
const storedHistory = JSON.parse(localStorage.getItem('history'));
|
||||
this.items = storedHistory || [];
|
||||
}
|
||||
|
||||
save() {
|
||||
localStorage.setItem('history', JSON.stringify(this.items));
|
||||
}
|
||||
|
||||
getPrevious() {
|
||||
if (this.index < this.items.length - 1) {
|
||||
return this.items[this.index++];
|
||||
}
|
||||
|
||||
return this.items[this.items.length - 1];
|
||||
}
|
||||
|
||||
getNext() {
|
||||
if (this.index > 0) {
|
||||
return this.items[--this.index];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.items = [];
|
||||
this.save();
|
||||
}
|
||||
}
|
||||
|
||||
export default History;
|
15
resources/assets/js/app.js
vendored
15
resources/assets/js/app.js
vendored
|
@ -1,14 +1,15 @@
|
|||
const form = document.getElementById('form');
|
||||
const input = document.getElementById('url');
|
||||
require('./bootstrap');
|
||||
const Vue = require('vue');
|
||||
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
Vue.component('terminal', require('./components/terminal.vue'));
|
||||
|
||||
form.action = input.value.toLowerCase();
|
||||
|
||||
form.submit();
|
||||
const app = new Vue({
|
||||
el: '#main',
|
||||
});
|
||||
|
||||
|
||||
const input = document.getElementById('url');
|
||||
|
||||
window.addEventListener('click', event => {
|
||||
event.stopPropagation();
|
||||
|
||||
|
|
13
resources/assets/js/bootstrap.js
vendored
Normal file
13
resources/assets/js/bootstrap.js
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
/** Configuration of Axios for Laravel */
|
||||
window.axios = require('axios');
|
||||
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
const token = document.head.querySelector('meta[name="csrf-token"]');
|
||||
|
||||
if (token) {
|
||||
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
|
||||
window.axios.defaults.headers.common['Accept'] = 'application/json';
|
||||
} else {
|
||||
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
|
||||
}
|
119
resources/assets/js/components/terminal.vue
Normal file
119
resources/assets/js/components/terminal.vue
Normal file
|
@ -0,0 +1,119 @@
|
|||
<template>
|
||||
<div>
|
||||
<h1
|
||||
v-if="results.length == 0"
|
||||
class="title">
|
||||
<span class="carret">~</span>
|
||||
dnsrecords.io
|
||||
</h1>
|
||||
<div
|
||||
v-for="result in results">
|
||||
<h1
|
||||
v-if="result.type == 'command'"
|
||||
class="title">
|
||||
<span class="carret">~</span>
|
||||
dnsrecords.io $ {{ result.message }}
|
||||
</h1>
|
||||
<pre
|
||||
v-else-if="result.type == 'default'"
|
||||
class="main__results"
|
||||
id="results"
|
||||
v-html="result.message"
|
||||
></pre>
|
||||
<p
|
||||
v-else-if="result.type == 'danger'"
|
||||
class="alert alert--danger"
|
||||
v-html="result.message"
|
||||
></p>
|
||||
<div
|
||||
v-else=""
|
||||
:class="'alert alert--' + result.type"
|
||||
role="alert"
|
||||
v-html="result.message"
|
||||
></div>
|
||||
</div>
|
||||
<span class="carret -green">→</span>
|
||||
<input
|
||||
id="url"
|
||||
name="command"
|
||||
placeholder="Enter a domain"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"
|
||||
autofocus="autofocus"
|
||||
spellcheck="false"
|
||||
v-model="input"
|
||||
v-on:keyup.enter="execute()"
|
||||
v-on:keydown.up="previous()"
|
||||
v-on:keydown.down="next()"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import History from '../History.js';
|
||||
export default {
|
||||
updated() {
|
||||
window.scrollTo(0, document.body.scrollHeight);
|
||||
},
|
||||
|
||||
mounted() {
|
||||
let hash = window.location.hash;
|
||||
if ('' !== hash) {
|
||||
this.input = hash.substr(1);
|
||||
this.execute();
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
results: [],
|
||||
input: '',
|
||||
history: new History()
|
||||
}
|
||||
},
|
||||
|
||||
methods : {
|
||||
send(command) {
|
||||
axios.get('/' + command).then(response => {
|
||||
this.results.push(response.data);
|
||||
})
|
||||
},
|
||||
|
||||
previous() {
|
||||
this.input = this.history.getPrevious();
|
||||
},
|
||||
|
||||
next() {
|
||||
this.input = this.history.getNext();
|
||||
},
|
||||
|
||||
execute() {
|
||||
let input = this.input;
|
||||
this.input = '';
|
||||
|
||||
this.history.add(input);
|
||||
this.results.push({
|
||||
'message' : input,
|
||||
'type': 'command',
|
||||
});
|
||||
window.location.hash = '#'+input;
|
||||
|
||||
switch(input)
|
||||
{
|
||||
case 'doom':
|
||||
window.location.href = "https://js-dos.com/games/doom.exe.html";
|
||||
return;
|
||||
|
||||
case 'clear':
|
||||
return this.results = [];
|
||||
|
||||
case 'history -c':
|
||||
return this.history.clear();
|
||||
|
||||
default:
|
||||
this.send(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,41 +1,8 @@
|
|||
@extends('layout.master')
|
||||
|
||||
@section('content')
|
||||
|
||||
<header class="header">
|
||||
<h1 class="title">
|
||||
<span class="carret">~</span>
|
||||
dnsrecords.io
|
||||
</h1>
|
||||
</header>
|
||||
<main class="main">
|
||||
@if(isset($output))
|
||||
<pre class="main__results" id="results">{{ $output }}</pre>
|
||||
@endif
|
||||
|
||||
@if($errors->has('input'))
|
||||
<p class="alert alert--danger">
|
||||
{{ $errors->first('input') }}
|
||||
</p>
|
||||
@endif
|
||||
@include('layout._partials.flash')
|
||||
|
||||
<form id="form" method="post" action="/">
|
||||
{{ csrf_field() }}
|
||||
|
||||
<span class="carret -green">→</span>
|
||||
<input
|
||||
id="url"
|
||||
name="command"
|
||||
placeholder="Enter a domain"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"
|
||||
autofocus="autofocus"
|
||||
spellcheck="false"
|
||||
/>
|
||||
|
||||
</form>
|
||||
<main id="main" class="main">
|
||||
<terminal></terminal>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
@foreach (session('flash_notification', collect())->toArray() as $message)
|
||||
<div class="alert alert--{{ $message['level'] }}
|
||||
{{ $message['important'] ? 'alert--important' : '' }}"
|
||||
role="alert"
|
||||
>
|
||||
{!! $message['message'] !!}
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
{{ session()->forget('flash_notification') }}
|
|
@ -20,6 +20,7 @@
|
|||
<link rel="manifest" href="/manifest.json">
|
||||
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#151d21">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
</head>
|
||||
|
||||
<body class="layout">
|
||||
|
|
Loading…
Add table
Reference in a new issue