Skip to content

Commit

Permalink
Adding the ability to add and remove precanned messages
Browse files Browse the repository at this point in the history
  • Loading branch information
nexxai committed Jul 25, 2023
1 parent 7301745 commit 744eaa2
Show file tree
Hide file tree
Showing 15 changed files with 366 additions and 74 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/RunTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,5 @@ jobs:
cp .env.example .env
php -v
php artisan key:generate
./vendor/bin/pest --parallel --coverage-clover=coverage.xml
./vendor/bin/pest --coverage-clover=coverage.xml
bash <(curl -s https://codecov.io/bash) || echo 'Codecov failed to upload'
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ yarn-error.log
/.idea
/.vscode
/config/lgtvs.php
/config/precanned.php
/public/aiowebostv/__pycache__
29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

Have you ever needed to send a message to someone in another room of your house who was watching TV with headphones on but wasn't great at checking their phone? Or maybe you just want to annoy the everliving crap out of your spouse? Then this app might be for you. Run it on a server in your house, connect to it from your phone, and have fun spamming your friends and family for years to come!


## What it looks like

### Interface

![Screenshot of the app interface](resources/images/interface.png)
Expand All @@ -16,12 +16,26 @@ Have you ever needed to send a message to someone in another room of your house

![Screenshot of message at the bottom of an LG webOS TV](resources/images/screenshot.jpg)


### Notes

- This service *must* be run on the same network as the TVs you wish to message. You cannot run this on a remote service like a droplet or AWS, unless you have a permanent VPN between the two sites.
- If you decide to expose this service to the world (e.g. via some kind of port forward), be aware that anyone who accesses the page will have unfettered access to the bottom of your TVs forever. If you absolutely must expose it to the internet, use something like a Cloudflare tunnel and then create a Cloudflare Access application, and only allow certain email addresses to browse to it (this is an exercise left up to the reader; PRs for better documentation are greatly appreciated.)

## Instructions

1. Run `composer install`, `npm install`, and `npm run build`
2. Run `php artisan lg:first-time`
3. Open the newly created `.env` file, and update the `APP_URL` fields to appropriate values
4. Point your web server's root directory to the `/public` folder in this distribution.

If you ever need to add another TV to the list, you can run `php artisan lg:add` and follow the prompts

## Precanned Messages

If you have any messages that you think you will send often (e.g. "Check your phone"), you can add them by running `php artisan lg:add-response "Check your phone"` - these will show up in a dropdown on the main page.

If you need to subsequently remove any of these messages, run `php artisan lg:remove-response` and follow the prompts to remove the appropriate one.

## Requirements

This app requires PHP, NodeJS *and* Python. You must have the following versions:
Expand All @@ -32,18 +46,9 @@ This app requires PHP, NodeJS *and* Python. You must have the following version
|Python |3.11.4 |
|NodeJS |20.5.0 |

## Instructions

1. Run `composer install`, `npm install`, and `npm run build`
2. Run `php artisan lg:first-time`
3. Open the newly created `.env` file, and update the `APP_URL` fields to appropriate values
4. Point your web server's root directory to the `/public` folder in this distribution.

If you ever need to add another TV to the list, you can run `php artisan lg:add` and follow the prompts

## Contributing

All PRs are welcome and very much appreciated. I whipped this together in a single evening, so there will *definitely* be places where this code could be improved.
All PRs are welcome and very much appreciated. I whipped this together in a single evening, so there will *definitely* be places where this code could be improved. Criticisms will be accepted when provided with proof of a $10 donation to your local food bank.

## Credits

Expand Down
31 changes: 31 additions & 0 deletions app/Console/Commands/AddPrecannedResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace App\Console\Commands;

use App\Services\ModifyConfig;
use Illuminate\Console\Command;

class AddPrecannedResponse extends Command
{
protected $signature = 'lg:add-response {
response : The response to store, wrapped in double quotes }';

protected $description = 'Add a precanned response (e.g. "Lili is awake")';

public string $file_path;

public function __construct()
{
parent::__construct();
$this->file_path = base_path().'/config/precanned.php';
}

public function handle()
{
$config = new ModifyConfig($this->file_path);

$config->add($this->argument('response'));

$this->components->info("Added '{$this->argument('response')}' to the list");
}
}
16 changes: 11 additions & 5 deletions app/Console/Commands/AddTVKeyToConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace App\Console\Commands;

use App\Services\ConfigMaintain;
use App\Services\ModifyConfig;
use App\Services\PythonExec;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Process;
Expand All @@ -13,9 +13,15 @@ class AddTVKeyToConfig extends Command

protected $description = 'Pair this app with your TV';

/**
* Execute the console command.
*/
public string $config_file_path;

public function __construct()
{
parent::__construct();

$this->config_file_path = base_path().'/config/lgtvs.php';
}

public function handle()
{
$name = $this->ask('Friendly name for the TV');
Expand Down Expand Up @@ -44,7 +50,7 @@ public function handle()
'ip' => $ip,
];

$config = new ConfigMaintain();
$config = new ModifyConfig($this->config_file_path);
$config->add($tvInstance);

$this->components->info("Added TV '{$name}' to the configuration");
Expand Down
9 changes: 5 additions & 4 deletions app/Console/Commands/FirstTimeSetup.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace App\Console\Commands;

use App\Services\ConfigMaintain;
use App\Services\CpExec;
use App\Services\ModifyConfig;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Process;

Expand All @@ -21,9 +21,10 @@ public function handle()
$this->components->info('.env file created');
}

if (! file_exists(base_path().'/config/lgtvs.php')) {
$config = new ConfigMaintain();
$config->create_lgtvs_file();
$config_file_path = base_path().'/config/lgtvs.php';
if (! file_exists($config_file_path)) {
$config = new ModifyConfig($config_file_path);
$config->create_blank_file();
$this->components->info('Config file created');
}

Expand Down
47 changes: 47 additions & 0 deletions app/Console/Commands/RemovePrecannedResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace App\Console\Commands;

use App\Services\ModifyConfig;
use Illuminate\Console\Command;

class RemovePrecannedResponse extends Command
{
protected $signature = 'lg:remove-response';

protected $description = 'Need to remove a saved response? Do it here.';

public string $file_path;

public function __construct()
{
parent::__construct();

$this->file_path = base_path() . '/config/precanned.php';
}

public function handle()
{

$config = new ModifyConfig($this->file_path);
$responseList = $config->read();

if (isset($responseList) && count($responseList) < 1) {
$this->components->warn('No stored responses found');
return 0;
}

$response = $this->choice('Which response would you like to remove', $responseList);
$response = intval($response);


$this->components->warn('About to remove:');
$this->line(' ' . $responseList[$response]);

$confirm = $this->components->confirm('Are you sure', false);

if ($confirm) {
$config->remove($response);
}
}
}
7 changes: 7 additions & 0 deletions app/Http/Livewire/MessagePage.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,20 @@ class MessagePage extends Component

public bool $sending = false;

public $precanned = [];

public function mount()
{
$tvs = config('lgtvs');

if (! empty($tvs)) {
$this->tvList = $tvs;
}

$precanned = config('precanned');
if (! empty($precanned)) {
$this->precanned = $precanned;
}
}

public function sendMessage(LGTVMessenger $messenger)
Expand Down
48 changes: 0 additions & 48 deletions app/Services/ConfigMaintain.php

This file was deleted.

70 changes: 70 additions & 0 deletions app/Services/ModifyConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace App\Services;

class ModifyConfig
{
public function __construct(public string $base_path, public bool $overwrite = false)
{
}

public function create_blank_file(): void
{
if (file_exists($this->base_path) && !$this->overwrite) {
return;
}

$empty_file = <<< 'PHP'
<?php
return [
];
PHP;

file_put_contents($this->base_path, $empty_file);
}

public function add($instance)
{
if (!file_exists($this->base_path)) {
$this->create_blank_file();
}

$contents = $this->read();

// Don't add a duplicate; just return without doing anything
if (in_array($instance, $contents)) {
return;
}

$contents[] = $instance;
$new_file = "<?php\n\nreturn " . $this->better_var_export($contents) . ';';
file_put_contents($this->base_path, $new_file);
}

public function remove(string $index)
{
$contents = $this->read();

unset($contents[$index]);

$file = "<?php\n\nreturn " . $this->better_var_export($contents) . ';';
file_put_contents($this->base_path, $file);
}

public function read()
{
return include $this->base_path;
}

protected function better_var_export($expression)
{
$export = var_export($expression, true);
$export = preg_replace('/^([ ]*)(.*)/m', '$1$1$2', $export);
$array = preg_split("/\r\n|\n|\r/", $export);
$array = preg_replace(["/\s*array\s\($/", "/\)(,)?$/", "/\s=>\s$/"], [null, ']$1', ' => ['], $array);
$export = implode(PHP_EOL, array_filter(['['] + $array));

return $export;
}
}
16 changes: 16 additions & 0 deletions resources/views/livewire/message-page.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@ class="w-full px-2 py-2 mb-4 text-3xl border rounded bg-slate-200 hover:ring-2 h
</select>
</div>

@if ($this->precanned)
<div class="mb-12 space-y-4 precanned">
<span class="block text-xl text-slate-400">Choose a saved message to send</span>
<select wire:model="messageToSend"
class="w-full px-2 py-2 mb-4 text-2xl border rounded bg-slate-200 hover:ring-2 hover:ring-green-600 hover:ring-offset-4 hover:ring-offset-slate-800 focus:outline-0">
<option selected="true" value="">Select a precanned message</option>
@foreach ($precanned as $key => $val)
<option value="{{ $val }}">{{ $val }}</option>
@endforeach
</select>
@error('precanned') <div x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 5000)"
class="block text-lg text-red-400 alert">{{ $message }}
</div>@enderror
</div>
@endif

<div class="mb-12 space-y-4">
<span class="block text-xl text-slate-400">Enter text to send to TV</span>
<input wire:model.defer="messageToSend" name="messageToSend"
Expand Down
Loading

0 comments on commit 744eaa2

Please sign in to comment.