diff --git a/.env b/.env index ee4d5da..cb29fab 100644 --- a/.env +++ b/.env @@ -18,3 +18,33 @@ APP_ENV=dev APP_SECRET=EDIT_ME ###< symfony/framework-bundle ### + +APP_VERSION=1.0.0 + +APP_NAME=KevaChat + +# Connect kevacoin + +APP_KEVACOIN_PROTOCOL=http +APP_KEVACOIN_HOST=127.0.0.1 +APP_KEVACOIN_PORT=9992 +APP_KEVACOIN_USERNAME=EDIT_ME +APP_KEVACOIN_PASSWORD=EDIT_ME + +# Default room namespace (must be owned to accept posts) +APP_KEVACOIN_NAMESPACE=EDIT_ME + +# Address to receive kevacoin powers (make others able to fill node balance) +APP_KEVACOIN_ADDRESS=EDIT_ME + +# Share with other some mining pool to get coins +APP_KEVACOIN_POOL_URL=https://kevacoin.hashvault.pro + +# Allow remotes to create new rooms (namespaces) +APP_ADD_ROOM_REMOTE_IP_REGEX=/.*/ + +# Allow remotes to create new posts (submit key/values) +APP_ADD_POST_REMOTE_IP_REGEX=/.*/ + +# Time quota for remote publications by IP (seconds) +APP_ADD_POST_REMOTE_IP_DELAY=60 \ No newline at end of file diff --git a/composer.json b/composer.json index 431a0a4..3eb0681 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "symfony/flex": "^2", "symfony/framework-bundle": "7.0.*", "symfony/runtime": "7.0.*", + "symfony/twig-bundle": "7.0.*", "symfony/yaml": "7.0.*" }, "config": { diff --git a/config/bundles.php b/config/bundles.php index 49d3fb6..bdd37ac 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -2,4 +2,5 @@ return [ Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], ]; diff --git a/config/packages/twig.yaml b/config/packages/twig.yaml new file mode 100644 index 0000000..03338b4 --- /dev/null +++ b/config/packages/twig.yaml @@ -0,0 +1,10 @@ +twig: + default_path: '%kernel.project_dir%/templates' + globals: + app: + version: '%app.version%' + name: '%app.name%' + +when@test: + twig: + strict_variables: true diff --git a/config/services.yaml b/config/services.yaml index 2d6a76f..5484d03 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -4,6 +4,17 @@ # Put parameters here that don't need to change on each machine where the app is deployed # https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration parameters: + app.version: '%env(APP_VERSION)%' + app.name: '%env(APP_NAME)%' + + app.kevacoin.protocol: '%env(APP_KEVACOIN_PROTOCOL)%' + app.kevacoin.host: '%env(APP_KEVACOIN_HOST)%' + app.kevacoin.port: '%env(APP_KEVACOIN_PORT)%' + app.kevacoin.username: '%env(APP_KEVACOIN_USERNAME)%' + app.kevacoin.password: '%env(APP_KEVACOIN_PASSWORD)%' + app.kevacoin.namespace: '%env(APP_KEVACOIN_NAMESPACE)%' + app.kevacoin.address: '%env(APP_KEVACOIN_ADDRESS)%' + app.kevacoin.pool.url: '%env(APP_KEVACOIN_POOL_URL)%' services: # default configuration for services in *this* file diff --git a/public/css/default.css b/public/css/default.css new file mode 100644 index 0000000..0ebadc4 --- /dev/null +++ b/public/css/default.css @@ -0,0 +1,105 @@ +* +{ + /* apply defaults */ + margin: 0; + padding: 0; + + /* allow draw */ + font-family: monospace; + + /* adaptive */ + color-scheme: light dark; + + /* vars */ + --container-max-width: 740px; +} + +*::placeholder +{ + font-size: 12px; +} + +a, a:active, a:visited +{ + text-decoration: none; +} + +a:hover +{ + text-decoration: underline; +} + +body +{ + font-size: 12px; + padding: 0 16px; +} + +header +{ + max-width: var(--container-max-width); + margin: 16px auto; + display: block; +} + +header > strong +{ + font-size: 14px; +} + +header > div +{ + margin: 8px 0; +} + +header > div > pre +{ + display: inline-block; +} + +main +{ + max-width: var(--container-max-width); + margin: 16px auto; + display: block; +} + +main > form > input[type="text"] +{ + box-sizing: border-box; + padding: 4px; + width: 100%; +} + +footer +{ + display: block; + margin: 16px auto; + max-width: var(--container-max-width); +} + +footer > form +{ + bottom: 16px; + display: block; + max-width: var(--container-max-width); + position: fixed; + width: 100%; +} + +footer > form > textarea +{ + box-sizing: border-box; + display: block; + margin: 8px 0; + max-width: var(--container-max-width); + padding: 4px; + width: 100%; +} + +footer > form > button +{ + cursor: pointer; + float: right; + padding: 2px 8px; +} \ No newline at end of file diff --git a/src/Controller/ModuleController.php b/src/Controller/ModuleController.php new file mode 100644 index 0000000..8882740 --- /dev/null +++ b/src/Controller/ModuleController.php @@ -0,0 +1,91 @@ +getParameter('app.kevacoin.protocol'), + $this->getParameter('app.kevacoin.host'), + $this->getParameter('app.kevacoin.port'), + $this->getParameter('app.kevacoin.username'), + $this->getParameter('app.kevacoin.password') + ); + + return $this->render( + 'default/module/info.html.twig', + [ + 'wallet' => + [ + 'balance' => (float) $client->getBalance(), + 'block' => (int) $client->getBlockCount(), + 'address' => $this->getParameter('app.kevacoin.address') + ], + 'pool' => [ + 'url' => $this->getParameter('app.kevacoin.pool.url') + ] + ] + ); + } + + public function room( + Request $request + ): Response + { + $client = new \Kevachat\Kevacoin\Client( + $this->getParameter('app.kevacoin.protocol'), + $this->getParameter('app.kevacoin.host'), + $this->getParameter('app.kevacoin.port'), + $this->getParameter('app.kevacoin.username'), + $this->getParameter('app.kevacoin.password') + ); + + return $this->render( + 'default/module/room.html.twig', + [ + 'room' => $request->get('room'), + 'list' => (array) $client->kevaListNamespaces() + ] + ); + } + + public function post( + Request $request + ): Response + { + $client = new \Kevachat\Kevacoin\Client( + $this->getParameter('app.kevacoin.protocol'), + $this->getParameter('app.kevacoin.host'), + $this->getParameter('app.kevacoin.port'), + $this->getParameter('app.kevacoin.username'), + $this->getParameter('app.kevacoin.password') + ); + + // Get wallet namespaces (to enable post module there) + $namespaces = []; + + foreach ((array) $client->kevaListNamespaces() as $key => $value) + { + $namespaces[] = $key; + } + + return $this->render( + 'default/module/post.html.twig', + [ + 'enabled' => in_array($request->get('namespace'), $namespaces), + 'namespace' => $request->get('namespace'), + 'message' => $request->get('message'), + 'user' => $request->get('user'), + 'ip' => $request->getClientIp() + ] + ); + } +} \ No newline at end of file diff --git a/src/Controller/RoomController.php b/src/Controller/RoomController.php new file mode 100644 index 0000000..45d3127 --- /dev/null +++ b/src/Controller/RoomController.php @@ -0,0 +1,122 @@ +redirectToRoute( + 'room_namespace', + [ + 'namespace' => $this->getParameter('app.kevacoin.namespace') + ] + ); + } + + #[Route( + '/room/{namespace}', + name: 'room_namespace', + requirements: + [ + 'namespace' => '^[A-z0-9]{34}$', + ], + methods: + [ + 'GET' + ] + )] + public function room( + Request $request + ): Response + { + // Connect kevacoin + $client = new \Kevachat\Kevacoin\Client( + $this->getParameter('app.kevacoin.protocol'), + $this->getParameter('app.kevacoin.host'), + $this->getParameter('app.kevacoin.port'), + $this->getParameter('app.kevacoin.username'), + $this->getParameter('app.kevacoin.password') + ); + + // Get room messages + $messages = []; + + foreach ((array) $client->kevaFilter($request->get('namespace')) as $message) + { + $messages[] = $message; + } + + // Return result + return $this->render( + 'default/room/index.html.twig', + [ + 'messages' => $messages, + 'request' => $request + ] + ); + } + + #[Route( + '/room/{namespace}/post', + name: 'room_post', + requirements: + [ + 'namespace' => '^[A-z0-9]{34}$', + ], + methods: + [ + 'POST' + ] + )] + public function post( + Request $request + ): Response + { + // Connect kevacoin + $client = new \Kevachat\Kevacoin\Client( + $this->getParameter('app.kevacoin.protocol'), + $this->getParameter('app.kevacoin.host'), + $this->getParameter('app.kevacoin.port'), + $this->getParameter('app.kevacoin.username'), + $this->getParameter('app.kevacoin.password') + ); + + // Check namespace exist for this wallet + $namespaces = []; + + foreach ((array) $client->kevaListNamespaces() as $key => $value) + { + $namespaces[] = $key; + } + + if (!in_array($request->get('namespace'), $namespaces)) + { + exit('Namespace not related with this node!'); + } + + // @TODO + + // Redirect back to the room + return $this->redirectToRoute( + 'room_namespace', + [ + 'namespace' => $this->getParameter('app.kevacoin.namespace') + ] + ); + } +} \ No newline at end of file diff --git a/templates/default/layout.html.twig b/templates/default/layout.html.twig new file mode 100644 index 0000000..7fc6ccf --- /dev/null +++ b/templates/default/layout.html.twig @@ -0,0 +1,33 @@ + + + + + {% block head_title %}{{ 'KevaChat' | trans }}{% endblock %} + + + +
+ + {{ app.name }} + + + {{ app.version }} + + {% block header_module_info %} + {{ + render( + controller( + 'App\\Controller\\ModuleController::info' + ) + ) + }} + {% endblock %} +
+
+ {% block main_content %}{% endblock %} +
+ + + \ No newline at end of file diff --git a/templates/default/module/info.html.twig b/templates/default/module/info.html.twig new file mode 100644 index 0000000..27faac4 --- /dev/null +++ b/templates/default/module/info.html.twig @@ -0,0 +1,14 @@ +
+ {{ 'Block:' | trans }} {{ wallet.block }} + / + {{ 'Balance:' | trans }} {{ wallet.balance }} + {% if wallet.address %} + / + {% if pool.url %} + {{ 'Charge' | trans }}: + {% else %} + {{ 'Charge:' | trans }} + {% endif %} +
{{ wallet.address }}
+ {% endif %} +
\ No newline at end of file diff --git a/templates/default/module/post.html.twig b/templates/default/module/post.html.twig new file mode 100644 index 0000000..63fe791 --- /dev/null +++ b/templates/default/module/post.html.twig @@ -0,0 +1,22 @@ +{% if enabled %} +
+ + {% if user == 'anonymous' or user != 'ip' %} + + {% else %} + + {% endif %} + + {% if user == 'ip' %} + + {% else %} + + {% endif %} + + +
+{% endif %} \ No newline at end of file diff --git a/templates/default/module/room.html.twig b/templates/default/module/room.html.twig new file mode 100644 index 0000000..d0daa2e --- /dev/null +++ b/templates/default/module/room.html.twig @@ -0,0 +1,3 @@ +
+ +
\ No newline at end of file diff --git a/templates/default/room/index.html.twig b/templates/default/room/index.html.twig new file mode 100644 index 0000000..95ee2b7 --- /dev/null +++ b/templates/default/room/index.html.twig @@ -0,0 +1,25 @@ +{% extends 'default/layout.html.twig' %} +{% block main_content %} + {{ + render( + controller( + 'App\\Controller\\ModuleController::room', + { + request: request + } + ) + ) + }} +{% endblock %} +{% block footer_content %} + {{ + render( + controller( + 'App\\Controller\\ModuleController::post', + { + request: request + } + ) + ) + }} +{% endblock %} \ No newline at end of file