generated from mirzaev/pot-php
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ef75a5814 | |||
| 4d2e419018 | |||
| 91d5883885 | |||
| 4203b1e9f8 | |||
| 658a95877c | |||
| 3ce62f13e2 | |||
| 1361f8cd5e | |||
| 323beeb886 | |||
| 9378f022b4 | |||
| 51e8214cd2 | |||
| 99daad5074 | |||
| eeca8fb535 | |||
| 77f62d53af |
8
.gitmodules
vendored
Normal file
8
.gitmodules
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
[submodule "pechatalka.mjs"]
|
||||
path = pechatalka.mjs
|
||||
url = https://git.svoboda.works/mirzaev/pechatalka.mjs
|
||||
branch = stable
|
||||
[submodule "damper.mjs"]
|
||||
path = damper.mjs
|
||||
url = https://git.svoboda.works/mirzaev/damper.mjs
|
||||
branch = stable
|
||||
53
README.md
53
README.md
@@ -1,2 +1,51 @@
|
||||
# pechatalka
|
||||
Chat-robot constructor for the Svoboda typography
|
||||
# Pechatalka
|
||||
Site and chat-robot constructor for the Svoboda typography
|
||||
|
||||
# Installation
|
||||
Before process any command think about **what it does** and whether the **paths** are specified correctly<br>
|
||||
|
||||
## NGINX
|
||||
### Create the NGINX server
|
||||
You can copy an example of the server file from here: `/examples/nginx/pechatalka.conf`<br>
|
||||
<small><i>I prefer to rename nginx config files to domain names. For example: `pechatalka.kodorvan.tech`</i></small><br>
|
||||
|
||||
<i>The file will be half commented out specifically to start the server for generating the TLS/SSL certificate</i><br>
|
||||
|
||||
1. `cd /examples/nginx`<br>
|
||||
2. `sudo cp pechatalka.conf /etc/nginx/sites-avaiable/pechatalka.conf`<br>
|
||||
3. `sudo nvim /etc/nginx/sites-avaiable/pechatalka.conf`<br>
|
||||
<small>3.1. <i>Customize the file according to your requirements</i></small><br>
|
||||
4. `sudo ln -s /etc/nginx/sites-avaiable/pechatalka.conf /etc/nginx/sites-enabled/pechatalka.conf`<br>
|
||||
5. `sudo nginx -t`<br>
|
||||
<small>5.1. <i>Make sure that <b>NGINX does not throw errors</b>, otherwise proceed to the instructions for generate a TLS/SSL certificate</i></small><br>
|
||||
6. `sudo service nginx restart`<br>
|
||||
|
||||
### Add mime-type recognition for javascript modules
|
||||
<small>Edit the file: `/etc/nginx/mime.types`</small><br>
|
||||
**From:** `application/javascript js;`<br>
|
||||
**To:** `application/javascript js mjs;`
|
||||
|
||||
### Generate a TLS/SSL sertificate (via [certbot](http://certbot.eff.org/) for [ubuntu](https://ubuntu.com/))
|
||||
1. `sudo apt install certbot python3-certbot-nginx`<br>
|
||||
2. `sudo certbot certonly --nginx`<br>
|
||||
<small><i>The **domain** must already be **bound** to the **IP-address** of the server by `CNAME`, `A` or `AAAA` record</i></small><br>
|
||||
3. Uncomment and reconfigure the nginx server file
|
||||
4. `sudo nginx -t`<br>
|
||||
<small>4.1. <i>Make sure that <b>NGINX does not throw errors</b></i></small><br>
|
||||
5. `sudo service nginx restart`
|
||||
|
||||
### Set up firewall rules for HTTP and HTTPS requests (for [ubuntu](https://ubuntu.com/))
|
||||
1. `sudo ufw allow "NGINX Full"`<br>
|
||||
<small>1.1. <i>Make sure that the <b>port for SSH connection</b> is open</i></small><br>
|
||||
2. `sudo ufw allow 22`<br>
|
||||
<small>2.1. <i>Use your SSH port instead of 22</i></small><br>
|
||||
3. `sudo ufw enable`
|
||||
|
||||
## SystemD (or any alternative you like)
|
||||
You can copy an example of the systemd file from here: `/examples/systemd/arming.service`<br>
|
||||
1. `cd examples/systemd`<br>
|
||||
2. `sudo cp pechatalka.service /etc/systemd/system/pechatalka.service && sudo chmod +x /etc/systemd/system/pechatalka.service`<br>
|
||||
3. `sudo nvim /etc/systemd/system/pechatalka.service`<br>
|
||||
<small>3.1. <i>Customize the file according to your requirements</i></small><br>
|
||||
4. `sudo systemctl daemon-reload`<br>
|
||||
3. `sudo systemctl enable pechatalka`<br>
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "mirzaev/pechatalka",
|
||||
"name": "svoboda/pechatalka",
|
||||
"description": "Chat-robot constructor for the Svoboda typography",
|
||||
"homepage": "https://git.svoboda.works/mirzaev/pechatalka",
|
||||
"homepage": "https://git.svoboda.works/svoboda/pechatalka",
|
||||
"type": "site",
|
||||
"keywords": [
|
||||
"minimal",
|
||||
@@ -15,32 +15,45 @@
|
||||
"name": "Arsen Mirzaev Tatyano-Muradovich",
|
||||
"email": "arsen@mirzaev.sexy",
|
||||
"homepage": "https://mirzaev.sexy",
|
||||
"role": "Programmer"
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"wiki": "https://git.svoboda.works/mirzaev/pechatalka/wiki",
|
||||
"issues": "https://git.svoboda.works/mirzaev/pechatalka/issues"
|
||||
"wiki": "https://git.svoboda.works/svoboda/pechatalka/wiki",
|
||||
"issues": "https://git.svoboda.works/svoboda/pechatalka/issues"
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.4",
|
||||
"mirzaev/minimal": "^3.6",
|
||||
"mirzaev/baza": "^3.3",
|
||||
"php": "^8.5",
|
||||
"ext-imagick": "^3.8",
|
||||
"mirzaev/minimal": "^3.10",
|
||||
"mirzaev/baza": "^3.4.3",
|
||||
"twig/twig": "^3.2",
|
||||
"twig/extra-bundle": "^3.7",
|
||||
"twig/intl-extra": "^3.10"
|
||||
"twig/intl-extra": "^3.10",
|
||||
"svoboda/time": "^1.0",
|
||||
"imagine/imagine": "^1.5",
|
||||
"badfarm/zanzara": "^0.9.1",
|
||||
"nyholm/psr7": "^1.8",
|
||||
"react/filesystem": "^0.1.2",
|
||||
"mirzaev/record": "^2.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"mirzaev\\pechatalka\\": "mirzaev/pechatalka/system"
|
||||
"svoboda\\pechatalka\\": "svoboda/pechatalka/system"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"mirzaev\\pechatalka\\tests\\": "mirzaev/pechatalka/tests"
|
||||
"svoboda\\pechatalka\\tests\\": "svoboda/pechatalka/tests"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"pre-update-cmd": "./install.sh"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"php-http/discovery": true,
|
||||
"wyrihaximus/composer-update-bin-autoload-path": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
damper.mjs
Submodule
1
damper.mjs
Submodule
Submodule damper.mjs added at 81d208b964
53
examples/nginx/pechatalka.conf
Normal file
53
examples/nginx/pechatalka.conf
Normal file
@@ -0,0 +1,53 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
|
||||
server_name pechatalka.svoboda.works;
|
||||
|
||||
# 301 302
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen 443 quic;
|
||||
listen [::]:443 ssl;
|
||||
listen [::]:443 quic;
|
||||
|
||||
server_name pechatalka.svoboda.works;
|
||||
|
||||
http2 on;
|
||||
http3 on;
|
||||
quic_gso on;
|
||||
quic_retry on;
|
||||
|
||||
add_header Alt-Svc 'h3=":$server_port"; ma=86400';
|
||||
add_header x-quic 'h3';
|
||||
|
||||
root /var/www/pechatalka.svoboda.works/svoboda/pechatalka/system/public;
|
||||
|
||||
index index.php;
|
||||
|
||||
keepalive_timeout 60;
|
||||
|
||||
include snippets/ssl-params.conf;
|
||||
include snippets/ssl-svoboda.conf;
|
||||
include snippets/php8_4.conf;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|mp3|ogg|ogv|webm|htc|woff2|woff)$ {
|
||||
expires 1M;
|
||||
access_log off;
|
||||
add_header Cache-Control "max-age=2629746, public";
|
||||
}
|
||||
|
||||
location ~* \.(?:css|js|mjs|min)$ {
|
||||
expires 1y;
|
||||
access_log off;
|
||||
add_header Cache-Control "max-age=31556952, public";
|
||||
}
|
||||
}
|
||||
|
||||
17
examples/systemd/pechatalka.service
Normal file
17
examples/systemd/pechatalka.service
Normal file
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=Telegram chat-robot: @domain_of_your_robot_here
|
||||
|
||||
Wants=network.target
|
||||
After=syslog.target network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=sudo -u www-data /usr/bin/php /var/www/pechatalka/svoboda/pechatalka/system/public/robot.php
|
||||
PIDFile=/var/run/php/pechatalka.pid
|
||||
RemainAfterExit=no
|
||||
RuntimeMaxSec=3600s
|
||||
Restart=always
|
||||
RestartSec=5s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
21
install.sh
21
install.sh
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
git submodule update --init --recursive
|
||||
|
||||
if [ -d author/project ]; then
|
||||
mv author/project author/pechatalka
|
||||
fi
|
||||
@@ -8,3 +10,22 @@ if [ -d author ]; then
|
||||
mv author mirzaev
|
||||
fi
|
||||
|
||||
for i in svoboda/pechatalka/system/settings/*.sample; do
|
||||
echo $i;
|
||||
if [ ! -f "${i/.sample/}" ]; then
|
||||
cp -n "$i" "${i/.sample/}";
|
||||
echo ${i/.sample/};
|
||||
fi
|
||||
done
|
||||
|
||||
if ! [ -d svoboda/pechatalka/system/public/js/modules ]; then
|
||||
mkdir svoboda/pechatalka/system/public/js/modules -p
|
||||
fi
|
||||
|
||||
if ! [ -L svoboda/pechatalka/system/public/js/modules/damper.mjs ]; then
|
||||
ln -s ../../../../../../damper.mjs/damper.mjs svoboda/pechatalka/system/public/js/modules/damper.mjs;
|
||||
fi
|
||||
|
||||
if ! [ -L svoboda/pechatalka/system/public/js/modules/pechatalka.mjs ]; then
|
||||
ln -s ../../../../../../pechatalka.mjs/pechatalka.mjs svoboda/pechatalka/system/public/js/modules/pechatalka.mjs;
|
||||
fi
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
pechatalka.mjs/pechatalka.mjs.min
|
||||
@@ -1,4 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
aside {
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--text-color: initial;
|
||||
--text-color-hover: initial;
|
||||
--text-color-active: initial;
|
||||
--text-notice-color: initial;
|
||||
--text-warning-color: initial;
|
||||
--text-selected-color: initial;
|
||||
--text-selected-background-color: initial;
|
||||
|
||||
--link-color: initial;
|
||||
--link-color-hover: initial;
|
||||
--link-color-active: initial;
|
||||
|
||||
color: var(--text-color);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--text-color: initial;
|
||||
--text-color-hover: initial;
|
||||
--text-color-active: initial;
|
||||
--text-notice-color: initial;
|
||||
--text-warning-color: initial;
|
||||
--text-selected-color: initial;
|
||||
--text-selected-background-color: initial;
|
||||
|
||||
--link-color: initial;
|
||||
--link-color-hover: initial;
|
||||
--link-color-active: initial;
|
||||
|
||||
color: var(--text-color);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
@import url('/css/fonts/fira.css');
|
||||
@import url('/css/fonts/hack.css');
|
||||
@import url('/css/fonts/dejavu.css');
|
||||
|
||||
@font-face {
|
||||
font-family: 'Commissioner';
|
||||
src: url('/fonts/commissioner.ttf');
|
||||
font-weight: 400;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
footer {
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
header {
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
body {
|
||||
margin: unset;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--gap);
|
||||
transition: 0s;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
:root {
|
||||
--gap: min(12px, 1rem);
|
||||
|
||||
/* font-family: , system-ui, sans-serif; */
|
||||
font-family: "dejavu";
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
border: none;
|
||||
transition: 0.1s ease-out;
|
||||
}
|
||||
|
||||
/* Selection */
|
||||
::selection {
|
||||
color: var(--text-selected-color);
|
||||
background: var(--text-selected-background-color);
|
||||
}
|
||||
|
||||
::-moz-selection {
|
||||
color: var(--text-selected-color);
|
||||
background: var(--text-selected-background-color);
|
||||
}
|
||||
|
||||
|
||||
.unselectable {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'endpoint' => 'unix:///var/run/arangodb3/arango.sock',
|
||||
'database' => 'pechatalka',
|
||||
'name' => 'pechatalka',
|
||||
'password' => ''
|
||||
];
|
||||
@@ -1,24 +0,0 @@
|
||||
{% block title %}
|
||||
<title>{% if head.title != empty %}{{ head.title }}{% else %}pechatalka by mirzaev{% endif %}</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block meta %}
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
{% for meta in head.metas %}
|
||||
<meta {% for name, value in meta.attributes %}{{ name }}="{{ value }}" {% endfor %}>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{% for element in css %}
|
||||
<link type="text/css" rel="stylesheet"{% if element.href %} href="{{ element.href }}"{% endif %} />
|
||||
{% endfor %}
|
||||
<link type="text/css" rel="stylesheet" href="/themes/default/css/fonts.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/default/css/system.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/default/css/header.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/default/css/main.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/default/css/aside.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/default/css/themes/default/footer.css" />
|
||||
<link type="text/css" rel="stylesheet" href="/themes/default/css/themes/default/colors.css" />
|
||||
{% endblock %}
|
||||
@@ -1,28 +0,0 @@
|
||||
{% extends "/themes/default/core.html" %}
|
||||
|
||||
{% use "/themes/default/header.html" with css as header_css, body as header, js as header_js %}
|
||||
{% use "/themes/default/aside.html" with css as aside_css, body as aside, js as aside_js %}
|
||||
{% use "/themes/default/footer.html" with css as footer_css, body as footer, js as footer_js %}
|
||||
|
||||
{% block css %}
|
||||
{{ block('header_css') }}
|
||||
{{ block('aside_css') }}
|
||||
{{ block('footer_css') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{{ block('header') }}
|
||||
{{ block('aside') }}
|
||||
<main>
|
||||
{% block main %}
|
||||
{{ main|raw }}
|
||||
{% endblock %}
|
||||
</main>
|
||||
{{ block('footer') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ block('footer_js') }}
|
||||
{{ block('header_js') }}
|
||||
{{ block('aside_js') }}
|
||||
{% endblock %}
|
||||
@@ -1,5 +0,0 @@
|
||||
{% block js %}
|
||||
{% for element in js %}
|
||||
<script {% if element.src %}src="{{ element.src }}"{% endif %} {% if element.type %}type="{{ element.type }}"{% endif %}>{{ element.innerText }}</script>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
Submodule pechatalka.mjs updated: a32ea39cf6...c94542bfd3
@@ -2,13 +2,12 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\pechatalka\controllers;
|
||||
namespace svoboda\pechatalka\controllers;
|
||||
|
||||
// Files of the project
|
||||
use mirzaev\pechatalka\views\templater,
|
||||
mirzaev\pechatalka\models\core as models,
|
||||
mirzaev\pechatalka\models\session,
|
||||
mirzaev\pechatalka\models\enumerations\language;
|
||||
use svoboda\pechatalka\views\templater,
|
||||
svoboda\pechatalka\models\core as models,
|
||||
svoboda\pechatalka\models\enumerations\language;
|
||||
|
||||
// Framework for PHP
|
||||
use mirzaev\minimal\core as minimal,
|
||||
@@ -19,7 +18,7 @@ use mirzaev\minimal\core as minimal,
|
||||
/**
|
||||
* Controllers core
|
||||
*
|
||||
* @package mirzaev\pechatalka\controllers
|
||||
* @package svoboda\pechatalka\controllers
|
||||
*
|
||||
* @param language $language Language
|
||||
* @param response $response Response
|
||||
@@ -29,7 +28,6 @@ use mirzaev\minimal\core as minimal,
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
* @author mirzaev <mail@domain.zone>
|
||||
*/
|
||||
class core extends controller
|
||||
{
|
||||
@@ -75,7 +73,7 @@ class core extends controller
|
||||
if (isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] === 'nginx-ssl early hints') return status::bruh->label;
|
||||
|
||||
// Initializing the view template engine instance
|
||||
$this->view = new templater($this->session);
|
||||
$this->view = new templater();
|
||||
|
||||
// For the extends system
|
||||
parent::__construct(core: $core);
|
||||
236
svoboda/pechatalka/system/controllers/generator.php
Executable file
236
svoboda/pechatalka/system/controllers/generator.php
Executable file
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\controllers;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\controllers\core,
|
||||
svoboda\pechatalka\models\paper,
|
||||
svoboda\pechatalka\models\product,
|
||||
/* svoboda\pechatalka\models\enumerations\paper\type as paper_type, */
|
||||
svoboda\pechatalka\models\enumerations\paper\format as paper_format,
|
||||
svoboda\pechatalka\models\enumerations\product\type as product_type;
|
||||
|
||||
// Framework for PHP
|
||||
use mirzaev\minimal\http\enumerations\content,
|
||||
mirzaev\minimal\http\enumerations\status;
|
||||
|
||||
/**
|
||||
* Generator
|
||||
*
|
||||
* @package svoboda\pechatalka\controllers
|
||||
*
|
||||
* @param array $errors Registry of errors
|
||||
*
|
||||
* @method null index() Main page
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class generator extends core
|
||||
{
|
||||
/**
|
||||
* Errors
|
||||
*
|
||||
* @var array $errors Registry of errors
|
||||
*/
|
||||
protected array $errors = [
|
||||
'system' => []
|
||||
];
|
||||
|
||||
/**
|
||||
* Pin
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function pin(): null
|
||||
{
|
||||
if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) {
|
||||
// Request for any response
|
||||
|
||||
// Render page
|
||||
$page = $this->view->render('/generator/pin/page.html');
|
||||
|
||||
// Sending response
|
||||
$this->response
|
||||
->start()
|
||||
->clean()
|
||||
->sse()
|
||||
->write($page)
|
||||
->validate($this->request)
|
||||
?->body()
|
||||
->end();
|
||||
|
||||
// Deinitializing rendered page
|
||||
unset($page);
|
||||
|
||||
// Exit (success)
|
||||
return null;
|
||||
}
|
||||
|
||||
// Exit (fail)
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print
|
||||
*
|
||||
* Assemble and generate the blank from products and prepare to printing
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function print(
|
||||
string $type = '',
|
||||
string $products = '',
|
||||
?string $canvas = null
|
||||
): null {
|
||||
// Type
|
||||
!empty($type) and $type = product_type::{$type} ?? null;
|
||||
|
||||
// Amount
|
||||
/* preg_match('/[\d]+/', (string) $amount, $matches);
|
||||
$amount = (int) $matches[0] ?? 1;
|
||||
unset($matches); */
|
||||
|
||||
// Initializing products data
|
||||
$products = json_decode($products, true, 16);
|
||||
|
||||
// Initializing the canvas data
|
||||
$canvas = json_decode($canvas, true, 16);
|
||||
|
||||
if ($type instanceof product_type && count($products) > 0) {
|
||||
// Initialized all required arguments
|
||||
|
||||
// Declaring the images buffer
|
||||
$images = [];
|
||||
|
||||
foreach ($this->request->files as $name => $file) {
|
||||
// Iterating over received files
|
||||
|
||||
// Deserializing the file type
|
||||
!empty($file['type']) && is_string($file['type']) and $file['type'] = content::from($file['type']) ?? null;
|
||||
|
||||
if (match ($file['type']) {
|
||||
content::jpeg,
|
||||
content::png,
|
||||
content::webp => true,
|
||||
default => false
|
||||
}) {
|
||||
// Passed the file type filter
|
||||
|
||||
// Writing into the images buffer
|
||||
$images[$name] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($products as $product => &$layers) {
|
||||
// Iterating over products
|
||||
|
||||
// Creating the product
|
||||
$instance = new product()->create(
|
||||
account: 0,
|
||||
type: $type,
|
||||
layers: $layers,
|
||||
canvas: $canvas
|
||||
);
|
||||
|
||||
// Initializing the product storage path
|
||||
$storage = STORAGE
|
||||
. DIRECTORY_SEPARATOR
|
||||
. 'products'
|
||||
. DIRECTORY_SEPARATOR
|
||||
. $instance->identifier;
|
||||
|
||||
if (!file_exists(filename: $storage)) {
|
||||
// The product storage directory is not created
|
||||
|
||||
if (mkdir(directory: $storage, permissions: 0755, recursive: true)) {
|
||||
// Created the product storage directory
|
||||
} else {
|
||||
// Nor created the product storage directory
|
||||
|
||||
// Exit (fail)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_filter($images, fn(string $key) => preg_match('/^' . $product . '_\d{1,2}$/', $key), ARRAY_FILTER_USE_KEY) as $name => $image) {
|
||||
// Iterating over the product images
|
||||
|
||||
// Initializing the layer
|
||||
preg_match('/\d{1,2}$/', $name, $matches);
|
||||
$layer = $matches[0];
|
||||
|
||||
if (!empty($layer) || $layer == 0) {
|
||||
// Initialized the layer
|
||||
|
||||
// Initializing the product layer image file path
|
||||
$path = $storage . DIRECTORY_SEPARATOR . $layer . '.' . $image['type']->extension();
|
||||
|
||||
if (copy(from: $image['tmp_name'], to: $path)) {
|
||||
// Copied the product layer image into the product storage
|
||||
|
||||
// Matching the product image with the product
|
||||
$layers[$layer]['image'] = $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($products as $product) {
|
||||
// Iterating over products
|
||||
|
||||
foreach ($product as $layer) {
|
||||
// Iterating over the product layer
|
||||
|
||||
if (empty($layer['image'])) {
|
||||
// Found the empty layer
|
||||
|
||||
// Exit (fail)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($type === product_type::pin_37) {
|
||||
// Pin 37mm
|
||||
|
||||
$biba = paper::generate(
|
||||
format: paper_format::a6,
|
||||
type: $type,
|
||||
products: $products,
|
||||
canvas: $canvas,
|
||||
dpi: 80,
|
||||
fit: true
|
||||
);
|
||||
}
|
||||
|
||||
if (str_contains($this->request->headers['accept'], content::any->value)) {
|
||||
// Request for any response
|
||||
|
||||
// Render page
|
||||
$page = $this->view->render('/generator/pin/page.html');
|
||||
|
||||
// Sending response
|
||||
$this->response
|
||||
->start()
|
||||
->clean()
|
||||
->sse()
|
||||
->write($page)
|
||||
->validate($this->request)
|
||||
?->body()
|
||||
->end();
|
||||
|
||||
// Deinitializing rendered page
|
||||
unset($page);
|
||||
|
||||
// Exit (success)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Exit (fail)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\pechatalka\controllers;
|
||||
namespace svoboda\pechatalka\controllers;
|
||||
|
||||
// Files of the project
|
||||
use mirzaev\pechatalka\controllers\core;
|
||||
use svoboda\pechatalka\controllers\core;
|
||||
|
||||
// Framework for PHP
|
||||
use mirzaev\minimal\http\enumerations\content,
|
||||
@@ -14,7 +14,7 @@ use mirzaev\minimal\http\enumerations\content,
|
||||
/**
|
||||
* Index
|
||||
*
|
||||
* @package mirzaev\pechatalka\controllers
|
||||
* @package svoboda\pechatalka\controllers
|
||||
*
|
||||
* @param array $errors Registry of errors
|
||||
*
|
||||
@@ -22,7 +22,6 @@ use mirzaev\minimal\http\enumerations\content,
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
* @author mirzaev <mail@domain.zone>
|
||||
*/
|
||||
final class index extends core
|
||||
{
|
||||
@@ -42,7 +41,7 @@ final class index extends core
|
||||
*/
|
||||
public function index(): null
|
||||
{
|
||||
if (str_contains($this->request->headers['accept'], content::any->value)) {
|
||||
if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) {
|
||||
// Request for any response
|
||||
|
||||
// Render page
|
||||
0
mirzaev/pechatalka/system/databases/.gitignore → svoboda/pechatalka/system/databases/.gitignore
vendored
Normal file → Executable file
0
mirzaev/pechatalka/system/databases/.gitignore → svoboda/pechatalka/system/databases/.gitignore
vendored
Normal file → Executable file
83
svoboda/pechatalka/system/localizations/english.php
Normal file
83
svoboda/pechatalka/system/localizations/english.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
// Exit (success)
|
||||
return [
|
||||
// System
|
||||
'svoboda' => 'Svoboda',
|
||||
'svoboda_work_union' => 'Svoboda Work Union',
|
||||
'svoboda_work_union_short' => 'SWU',
|
||||
'pechatalka' => 'Pechatalka',
|
||||
'empty' => 'Empty',
|
||||
'yes' => 'Yes',
|
||||
'no' => 'No',
|
||||
|
||||
// Main menu
|
||||
'menu_title' => 'Main menu',
|
||||
'menu_accounts' => 'Accounts',
|
||||
'menu_button_generator_pin' => 'Pin',
|
||||
'menu_not_syncronized' => 'The database does not synchronize with the blockchain network',
|
||||
|
||||
// Account
|
||||
'account_title' => 'Account',
|
||||
'account_export' => 'This account can be exported to the Svoboda main blockchain network in the future',
|
||||
'account_data' => "⚠️ Your data may be given to the special services of Russia\nBe careful and think with your head.",
|
||||
'account_security_repository' => 'Information security',
|
||||
'account_security_repository_mirror_github' => 'mirror',
|
||||
'account_authorized_system' => 'Access to the system',
|
||||
'account_authorized_settings' => 'Access to settings',
|
||||
'account_authorized_system_accounts' => 'System access to accounts management',
|
||||
'account_authorized_system_settings' => 'System access to the system settings',
|
||||
'account_button_localizations' => 'Localizations',
|
||||
'account_localization_create_failted_to_initialize_language' => 'Failed to initialize language',
|
||||
|
||||
// Language setting
|
||||
'settings_select_language_title' => 'Select language',
|
||||
'settings_select_language_description' => 'The selected language will be writed in your account settings',
|
||||
'settings_language_update_success' => 'Language replaced:',
|
||||
'settings_language_update_fail' => 'Failed to replace language',
|
||||
|
||||
// Language selection
|
||||
'select_language_title' => 'Select language',
|
||||
'select_language_description' => 'The selected language will be used in the current process',
|
||||
'select_language_button_add' => 'Add a language',
|
||||
|
||||
// Repository
|
||||
'repository_title' => 'Repository',
|
||||
'repository_text' => <<<TXT
|
||||
Pechatalka is written in [PHP](https://www.php.net/) using [Zanzara](https://github.com/badfarm/zanzara) for Telegram,
|
||||
my [MINIMAL](https://git.svoboda.works/mirzaev/minimal) framework for PHP and my [Baza](https://git.svoboda.works/mirzaev/baza) database
|
||||
|
||||
The code is under the [WTFPL](https://en.wikipedia.org/wiki/WTFPL) license
|
||||
You can help me with the development, or use my code for free\!
|
||||
TXT,
|
||||
'repository_button_code' => 'The code',
|
||||
'repository_button_issues' => 'Issues',
|
||||
'repository_button_suggestions' => 'Suggestions',
|
||||
|
||||
// Author
|
||||
'author_title' => 'Author',
|
||||
'author_text' => <<<TXT
|
||||
*Arsen Mirzaev Tatyano\-Muradovich*
|
||||
Programmer, anarchist, vegetarian
|
||||
TXT,
|
||||
'author_button_neurojournal' => 'Neurojournal',
|
||||
'author_button_projects' => 'Projects',
|
||||
'author_button_telegram' => 'Telegram',
|
||||
'author_button_twitter' => 'Twitter',
|
||||
'author_button_bluesky' => 'Bluesky',
|
||||
'author_button_bastyon' => 'Bastyon',
|
||||
'author_button_youtube_english' => 'YouTube',
|
||||
'author_button_youtube_russian' => 'YouTube',
|
||||
'author_button_message' => 'Send a message',
|
||||
|
||||
// Authorization
|
||||
'not_authorized_system' => 'You do not have access to the system',
|
||||
'not_authorized_messages' => 'You do not have access to send messages',
|
||||
'not_authorized_joins' => 'You do not have access to joins',
|
||||
'not_authorized_settings' => 'You do not have access to the settings',
|
||||
'not_authorized_system_settings' => 'You do not have access to the system settings',
|
||||
'not_authorized_system_distributions' => 'You do not have access to distributions administration',
|
||||
|
||||
// Other
|
||||
'why_so_shroomious' => 'why so shroomious'
|
||||
];
|
||||
88
svoboda/pechatalka/system/localizations/russian.php
Normal file
88
svoboda/pechatalka/system/localizations/russian.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
// Exit (success)
|
||||
return [
|
||||
// System
|
||||
'svoboda' => 'Свобода',
|
||||
'svoboda_work_union' => 'Рабочий Союз Свободы',
|
||||
'svoboda_work_union_short' => 'РСС',
|
||||
'Pechatalka' => 'Печаталка',
|
||||
'empty' => 'Пусто',
|
||||
'yes' => 'Да',
|
||||
'no' => 'Нет',
|
||||
|
||||
// Main menu
|
||||
'menu_title' => 'Главное меню',
|
||||
'menu_accounts' => 'Аккаунты',
|
||||
'menu_button_generator_pin' => 'Значок',
|
||||
'menu_not_syncronized' => 'База данных не синхронизируется с блокчейн сетью',
|
||||
|
||||
// Аккаунт
|
||||
'account_title' => 'Аккаунт',
|
||||
'account_export' => 'Этот аккаунт может быть экспортирован в основную блокчейн сеть Свободы в будущем',
|
||||
'account_data' => "⚠️ Твои данные могут быть выданы спецслужбам России\nБудь осторожен и думай своей головой",
|
||||
'account_security_repository' => 'Информационная безопасность',
|
||||
'account_security_repository_mirror_github' => 'зеркало',
|
||||
'account_authorized_system' => 'Доступ к системе',
|
||||
'account_authorized_messages' => 'Доступ к сообщениям',
|
||||
'account_authorized_joins' => 'Доступ к вступлениям',
|
||||
'account_authorized_settings' => 'Доступ к изменению настроек',
|
||||
'account_authorized_system_accounts' => 'Системный доступ к управлению аккаунтами',
|
||||
'account_authorized_system_distributions' => 'Системный доступ к управлению дистрибутивами',
|
||||
'account_authorized_system_members' => 'Системный доступ к управлению участниками дистрибутивов',
|
||||
'account_authorized_system_settings' => 'Системный доступ к системным настройкам',
|
||||
'account_button_localizations' => 'Локализации',
|
||||
'account_localization_create_failted_to_initialize_language' => 'Не удалось инициализировать язык',
|
||||
|
||||
// Настройки языка
|
||||
'settings_select_language_title' => 'Выбери язык',
|
||||
'settings_select_language_description' => 'Выбранный язык будет записан в настройки аккаунта',
|
||||
'settings_language_update_success' => 'Язык заменён:',
|
||||
'settings_language_update_fail' => 'Не удалось заменить язык',
|
||||
|
||||
// Выбор языка
|
||||
'select_language_title' => 'Выбери язык',
|
||||
'select_language_description' => 'Выбранный язык будет использован в текущем процессе',
|
||||
'select_language_button_add' => 'Добавить язык',
|
||||
|
||||
// Репозиторий
|
||||
'repository_title' => 'Репозиторий',
|
||||
'repository_text' => <<<TXT
|
||||
Печаталка написана на [PHP](https://www.php.net/) используя [Zanzara](https://github.com/badfarm/zanzara) для Telegram,
|
||||
мой [MINIMAL](https://git.svoboda.works/mirzaev/minimal) фреймворк для PHP и моя база данных [Baza](https://git.svoboda.works/mirzaev/baza)
|
||||
|
||||
Код находится под лицензией [WTFPL](https://en.wikipedia.org/wiki/WTFPL)
|
||||
Помогай с разработкой или используй мой код бесплатно\!
|
||||
TXT,
|
||||
'repository_button_code' => 'Код',
|
||||
'repository_button_issues' => 'Проблемы',
|
||||
'repository_button_suggestions' => 'Предложения',
|
||||
|
||||
// Автор
|
||||
'author_title' => 'Автор',
|
||||
'author_text' => <<<TXT
|
||||
*Арсен Мирзаев Татьяно\-Мурадович*
|
||||
Программист, анархист, вегетарианец
|
||||
TXT,
|
||||
'author_button_neurojournal' => 'Нейрожурнал',
|
||||
'author_button_projects' => 'Проекты',
|
||||
'author_button_telegram' => 'Телеграм',
|
||||
'author_button_twitter' => 'Twitter',
|
||||
'author_button_bluesky' => 'Bluesky',
|
||||
'author_button_bastyon' => 'Bastyon',
|
||||
'author_button_youtube_english' => 'YouTube',
|
||||
'author_button_youtube_russian' => 'YouTube',
|
||||
'author_button_message' => 'Отправить сообщение',
|
||||
|
||||
// Авторизация
|
||||
'not_authorized_system' => 'У тебя нет доступа к системе',
|
||||
'not_authorized_messages' => 'У тебя нет доступа к сообщениям',
|
||||
'not_authorized_joins' => 'У тебя нет доступа к вступлениям',
|
||||
'not_authorized_settings' => 'У тебя нет доступа к настройкам',
|
||||
'not_authorized_system_settings' => 'У тебя нет доступа к системным настройкам',
|
||||
'not_authorized_system_distributions' => 'У тебя нет доступа к администрированию дистрибутивов',
|
||||
|
||||
// Прочее
|
||||
'why_so_shroomious' => 'почему такой грибъёзный'
|
||||
|
||||
];
|
||||
202
svoboda/pechatalka/system/models/account.php
Normal file
202
svoboda/pechatalka/system/models/account.php
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\core;
|
||||
|
||||
// Svoboda time
|
||||
use svoboda\time\statement as svoboda;
|
||||
|
||||
// Baza database
|
||||
use mirzaev\baza\database,
|
||||
mirzaev\baza\column,
|
||||
mirzaev\baza\record,
|
||||
mirzaev\baza\enumerations\encoding,
|
||||
mirzaev\baza\enumerations\type;
|
||||
|
||||
// Framework for Telegram
|
||||
use Zanzara\Telegram\Type\User as telegram;
|
||||
|
||||
// Built-in libraries
|
||||
use Exception as exception,
|
||||
RuntimeException as exception_runtime;
|
||||
|
||||
/**
|
||||
* Account
|
||||
*
|
||||
* @package svoboda\pechatalka\models
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class account extends core
|
||||
{
|
||||
/**
|
||||
* File
|
||||
*
|
||||
* @var string $database Path to the database file
|
||||
*/
|
||||
protected string $file = DATABASES . DIRECTORY_SEPARATOR . 'accounts.baza';
|
||||
|
||||
/**
|
||||
* Database
|
||||
*
|
||||
* @var database $database The database
|
||||
*/
|
||||
public protected(set) database $database;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Initializing the database
|
||||
$this->database = new database()
|
||||
->encoding(encoding::utf8)
|
||||
->columns(
|
||||
new column('identifier', type::integer_unsigned),
|
||||
new column('identifier_telegram', type::integer),
|
||||
new column('domain', type::string, ['length' => 32]),
|
||||
new column('name_first', type::string, ['length' => 64]),
|
||||
new column('name_second', type::string, ['length' => 64]),
|
||||
new column('language', type::string, ['length' => 2]),
|
||||
new column('robot', type::char),
|
||||
new column('authorized_system', type::char),
|
||||
new column('authorized_settings', type::char),
|
||||
new column('authorized_system_accounts', type::char),
|
||||
new column('authorized_system_settings', type::char),
|
||||
new column('updated', type::integer_unsigned),
|
||||
new column('created', type::integer_unsigned)
|
||||
)
|
||||
->connect($this->file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*
|
||||
* Searches for the account record in the database, and if it does not find it, then creates it
|
||||
*
|
||||
* @param telegram $telegram The telegram account
|
||||
*
|
||||
* @throws exception_runtime if update the account record in the database by the telegram account values
|
||||
* @throws exception_runtime if failed to find the registered account
|
||||
* @throws exception_runtime if failed to registrate the account
|
||||
*
|
||||
* @return record The account record from the database
|
||||
*/
|
||||
public function initialize(telegram $telegram): record
|
||||
{
|
||||
// Searching for the account in the database
|
||||
$account = $this->database->read(filter: fn(record $record) => $record->identifier_telegram === $telegram->getId(), amount: 1)[0] ?? null;
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Found the account record
|
||||
|
||||
if (
|
||||
$account->name_first !== $telegram->getFirstName() ||
|
||||
$account->name_second !== $telegram->getLastName() ||
|
||||
$account->domain !== $telegram->getUsername()
|
||||
) {
|
||||
// The telegram account was updated
|
||||
|
||||
// Updating the account in the database
|
||||
$updated = $this->database->read(
|
||||
filter: fn(record $record) => $record->identifier_telegram === $telegram->getId(),
|
||||
update: function (record &$record) use ($telegram){
|
||||
// Writing new values into the record
|
||||
$record->name_first = $telegram->getFirstName();
|
||||
$record->name_second = $telegram->getLastName();
|
||||
$record->domain = $telegram->getUsername();
|
||||
$record->updated = svoboda::timestamp();
|
||||
},
|
||||
amount: 1
|
||||
)[0] ?? null;
|
||||
|
||||
if ($updated instanceof record && $updated->values() !== $account->values()) {
|
||||
// Updated the account in the database
|
||||
|
||||
// Exit (success)
|
||||
return $updated;
|
||||
} else {
|
||||
// Not updated the account in the database
|
||||
|
||||
// Exit (fail)
|
||||
throw new exception_runtime('Failed to update the account record in the database by the telegram account values');
|
||||
}
|
||||
}
|
||||
|
||||
// Exit (success)
|
||||
return $account;
|
||||
} else {
|
||||
// Not found the account record
|
||||
|
||||
if ($this->registrate($telegram)) {
|
||||
// Registered the account
|
||||
|
||||
// Searching for the registered account in the database
|
||||
$account = $this->database->read(filter: fn(record $record) => $record->identifier_telegram === $telegram->getId(), amount: 1)[0] ?? null;
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Found the registered account
|
||||
|
||||
// Exit (success)
|
||||
return $account;
|
||||
} else {
|
||||
// Not found the registered account
|
||||
|
||||
// Exit (fail)
|
||||
throw new exception_runtime('Failed to find the registered account');
|
||||
}
|
||||
} else {
|
||||
// Not registered the account
|
||||
|
||||
// Exit (fail)
|
||||
throw new exception_runtime('Failed to registrate the account');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registrate
|
||||
*
|
||||
* Creates the account record in the database
|
||||
*
|
||||
* @param telegram $telegram The telegram account
|
||||
*
|
||||
* @return int|false The record identifier, if created
|
||||
*/
|
||||
public function registrate(telegram $telegram): int|false
|
||||
{
|
||||
// Initializing the identifier
|
||||
$identifier = $this->database->count() + 1;
|
||||
|
||||
// Initializing the record
|
||||
$record = $this->database->record(
|
||||
$identifier,
|
||||
(int) $telegram->getId(),
|
||||
$telegram->getFirstName(),
|
||||
$telegram->getLastName(),
|
||||
$telegram->getUsername(),
|
||||
$telegram->getLanguageCode(),
|
||||
(int) $telegram->isBot(),
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
svoboda::timestamp(),
|
||||
svoboda::timestamp()
|
||||
);
|
||||
|
||||
// Creating the record in the database
|
||||
$created = $this->database->write($record);
|
||||
|
||||
// Exit (success)
|
||||
return $created ? $identifier : false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\pechatalka\models;
|
||||
namespace svoboda\pechatalka\models;
|
||||
|
||||
// Framework for PHP
|
||||
use mirzaev\minimal\model,
|
||||
@@ -14,13 +14,12 @@ use exception;
|
||||
/**
|
||||
* Models core
|
||||
*
|
||||
* @package mirzaev\pechatalka\models
|
||||
* @package svoboda\pechatalka\models
|
||||
*
|
||||
* @method void __construct() Constructor
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
* @author mirzaev <mail@domain.zone>
|
||||
*/
|
||||
class core extends model
|
||||
{
|
||||
@@ -38,8 +37,5 @@ class core extends model
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
public function __construct() {}
|
||||
}
|
||||
|
||||
70
svoboda/pechatalka/system/models/enumerations/currency.php
Normal file
70
svoboda/pechatalka/system/models/enumerations/currency.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models\enumerations;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\enumerations\language;
|
||||
|
||||
/**
|
||||
* Types of currencies by ISO 4217 standart
|
||||
*
|
||||
* @package svoboda\pechatalka\models\enumerations
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
enum currency
|
||||
{
|
||||
case usd;
|
||||
case rub;
|
||||
|
||||
/**
|
||||
* Label
|
||||
*
|
||||
* Initialize label of the currency
|
||||
*
|
||||
* @param language|null $language Language into which to translate
|
||||
*
|
||||
* @return string Translated label of the currency
|
||||
*
|
||||
* @todo
|
||||
* 1. More currencies
|
||||
* 2. Cases???
|
||||
*/
|
||||
public function label(?language $language = language::en): string
|
||||
{
|
||||
// Exit (success)
|
||||
return match ($this) {
|
||||
currency::usd => match ($language) {
|
||||
language::en => 'Dollar',
|
||||
language::ru => 'Доллар'
|
||||
},
|
||||
currency::rub => match ($language) {
|
||||
language::en => 'Ruble',
|
||||
language::ru => 'Рубль'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Symbol
|
||||
*
|
||||
* Initialize symbol of the currency
|
||||
*
|
||||
* @return string Symbol of the currency
|
||||
*
|
||||
* @todo
|
||||
* 1. More currencies
|
||||
*/
|
||||
public function symbol(): string
|
||||
{
|
||||
// Exit (success)
|
||||
return match ($this) {
|
||||
currency::usd => '$',
|
||||
currency::rub => '₽'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\pechatalka\models\enumerations;
|
||||
namespace svoboda\pechatalka\models\enumerations;
|
||||
|
||||
/**
|
||||
* Language
|
||||
*
|
||||
* Types of languages by ISO 639-1 standart
|
||||
*
|
||||
* @package mirzaev\pechatalka\models\enumerations
|
||||
* @package svoboda\pechatalka\models\enumerations
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models\enumerations\paper;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\enumerations\product\type as product_type;
|
||||
|
||||
/**
|
||||
* Types of products
|
||||
*
|
||||
* @package svoboda\pechatalka\models\enumerations\paper
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
enum format
|
||||
{
|
||||
case a6;
|
||||
|
||||
/**
|
||||
* Dimensions
|
||||
*
|
||||
* @return array The paper format dimensions in centimeters (cm) ['width', 'height']
|
||||
*/
|
||||
public function dimensions(): array
|
||||
{
|
||||
return match ($this) {
|
||||
format::a6 => [
|
||||
'width' => 10.5,
|
||||
'height' => 14.8
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Places
|
||||
*
|
||||
* @param product_type $type The product type
|
||||
* @param int|float $padding The paper padding (print borders)
|
||||
*
|
||||
* @return array The paper places by the product type in centimeters (cm)
|
||||
*/
|
||||
public function places(product_type $type, int|float $padding = 0): array|false
|
||||
{
|
||||
if ($this === format::a6) {
|
||||
// A6
|
||||
|
||||
// Initializing the paper dimensions
|
||||
$paper = $this->dimensions();
|
||||
|
||||
if ($type === product_type::pin_37) {
|
||||
// Pin 37mm
|
||||
|
||||
// Initializing the product dimensions
|
||||
$blank = $type->areas()['blank'];
|
||||
|
||||
// Calculating the general X coordinate
|
||||
$x = $paper['width'] / 2 - $blank['width'] / 2 - $padding;
|
||||
|
||||
// Initializing the amount of products
|
||||
$amount = 2;
|
||||
|
||||
// Calculating the summary products height
|
||||
$height = $blank['height'] * $amount;
|
||||
|
||||
// Calculating the free space on the page
|
||||
$free = $paper['height'] - $padding * 2 - $height;
|
||||
|
||||
// Calculating the offset between products and from products to the paper borders
|
||||
$offset = $free / ($amount + 1);
|
||||
|
||||
// Exit (success)
|
||||
return [
|
||||
[
|
||||
'x' => $x,
|
||||
'y' => $offset
|
||||
],
|
||||
[
|
||||
'x' => $x,
|
||||
'y' => $offset + $blank['height'] + $offset
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Exit (fail)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models\enumerations\product;
|
||||
|
||||
/**
|
||||
* Types of products
|
||||
*
|
||||
* @package svoboda\pechatalka\models\enumerations\product
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
enum type
|
||||
{
|
||||
case pin_37;
|
||||
|
||||
/**
|
||||
* Areas
|
||||
*
|
||||
* @return array The product type areas in centimeters (cm) ['visible' => ['width', 'height'], 'blank' => ['width', 'height']]
|
||||
*/
|
||||
public function areas(): array
|
||||
{
|
||||
return match ($this) {
|
||||
type::pin_37 => [
|
||||
'visible' => [
|
||||
'width' => 3.7,
|
||||
'height' => 3.7
|
||||
],
|
||||
'blank' => [
|
||||
'width' => 4.85,
|
||||
'height' => 4.85
|
||||
]
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
214
svoboda/pechatalka/system/models/paper.php
Normal file
214
svoboda/pechatalka/system/models/paper.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\core,
|
||||
/* svoboda\pechatalka\models\enumerations\paper\type as paper_type, */
|
||||
svoboda\pechatalka\models\enumerations\paper\format as paper_format,
|
||||
svoboda\pechatalka\models\enumerations\product\type as product_type;
|
||||
|
||||
// Svoboda time
|
||||
use svoboda\time\statement as svoboda;
|
||||
|
||||
// Baza database
|
||||
use mirzaev\baza\database,
|
||||
mirzaev\baza\column,
|
||||
mirzaev\baza\record,
|
||||
mirzaev\baza\enumerations\encoding,
|
||||
mirzaev\baza\enumerations\type;
|
||||
|
||||
// Framework for Telegram
|
||||
use Zanzara\Telegram\Type\User as telegram;
|
||||
|
||||
// Built-in libraries
|
||||
use Imagick as imagick,
|
||||
ImagickKernel as imagick_kernel,
|
||||
ImagickPixel as imagick_pixel,
|
||||
ImagickDraw as imagick_draw,
|
||||
Exception as exception,
|
||||
RuntimeException as exception_runtime;
|
||||
|
||||
/**
|
||||
* Paper
|
||||
*
|
||||
* @package svoboda\pechatalka\models
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class paper extends core
|
||||
{
|
||||
/**
|
||||
* Generate
|
||||
*
|
||||
* @param paper_format $format
|
||||
* @param product_type $type
|
||||
* @param array $products
|
||||
* @param array $canvas
|
||||
* @param int|float $dpi Dots (pixels) per Inch (used with centimeters)
|
||||
* @param bool $fit Fit the maximum number of blanks on paper? (duplication)
|
||||
*
|
||||
* @return record The account record from the database
|
||||
*/
|
||||
public static function generate(paper_format $format, product_type $type, array $products, array $canvas = [], int|float $dpi = 300, bool $fit = true): mixed
|
||||
{
|
||||
// Initializing the paper dimensions
|
||||
$dimensions = $format->dimensions();
|
||||
$width = (int) round($dimensions['width'] * $dpi);
|
||||
$height = (int) round($dimensions['height'] * $dpi);
|
||||
unset($dimensions);
|
||||
|
||||
// Initializing the product areas
|
||||
$areas = $type->areas();
|
||||
|
||||
// Calculating the product blank dimensions by the print $dpi
|
||||
$blank = [
|
||||
'width' => (int) round($areas['blank']['width'] * $dpi),
|
||||
'height' => (int) round($areas['blank']['height'] * $dpi)
|
||||
];
|
||||
|
||||
// Calculating the $dpi ratio of the pechatalka interface to the blank dimensions
|
||||
$ratio = [
|
||||
'width' => $blank['width'] / $canvas['width'],
|
||||
'height' => $blank['height'] / $canvas['height']
|
||||
];
|
||||
|
||||
// Initializing the circle mask
|
||||
$mask = new imagick();
|
||||
$mask->setResolution($dpi, $dpi);
|
||||
$mask->newImage($blank['width'], $blank['height'], '#0000');
|
||||
$mask->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER);
|
||||
$mask->setimageformat('png');
|
||||
$mask->setimagematte(true);
|
||||
$draw = new imagick_draw();
|
||||
$draw->setfillcolor('#fff');
|
||||
$draw->circle($blank['width'] / 2, $blank['height'] / 2, $blank['width'] / 2, $blank['height']);
|
||||
$mask->drawimage($draw);
|
||||
|
||||
// Initializing the paper places
|
||||
$places = $format->places(type: $type);
|
||||
|
||||
// Calculating the amount of products
|
||||
$have = count($products);
|
||||
|
||||
// Calculating the amount of places per paper
|
||||
$limit = count($places);
|
||||
|
||||
// Calculating the amount of missing products on the paper
|
||||
$need = $limit - $have;
|
||||
|
||||
if ($fit && $have < $limit) {
|
||||
// Received less products then can be fit on the page
|
||||
|
||||
for (; $need++ < $limit;) {
|
||||
// Iterating over free places
|
||||
|
||||
// Dublicating the product
|
||||
$products[] = $products[rand(0, $have - 1)];
|
||||
}
|
||||
}
|
||||
|
||||
// Calculating the amount of papers
|
||||
$amount = $have % $limit;
|
||||
|
||||
for ($page = 0; $page < $amount; $page++) {
|
||||
// Iterating over pages
|
||||
|
||||
// Initializing the paper
|
||||
$paper = new imagick();
|
||||
$paper->setResolution($dpi, $dpi);
|
||||
$paper->newImage($width, $height, new imagick_pixel("#fff"));
|
||||
$paper->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER);
|
||||
$paper->setImageFormat("jpg");
|
||||
$paper->setimagematte(true);
|
||||
|
||||
// Calculating the products pages offset
|
||||
$offset = $page === 0 ? 0 : $page * $amount;
|
||||
|
||||
foreach ($places as $index => $place) {
|
||||
// Iterating over places
|
||||
|
||||
// Recalculating the place coordinates with DPI
|
||||
$place['x'] *= $dpi;
|
||||
$place['y'] *= $dpi;
|
||||
|
||||
// Initializing the product
|
||||
$product = $products[$offset + $index];
|
||||
|
||||
foreach ($product as $layer) {
|
||||
// Iterating over the product layers
|
||||
|
||||
// Filtering and normalizing the layer parameters
|
||||
empty($layer['scale']) || $layer['scale'] == 0 and $layer['scale'] = 1;
|
||||
|
||||
// Initializing the layer image
|
||||
$image = new imagick();
|
||||
$image->setResolution($dpi, $dpi);
|
||||
$image->readImage($layer['image']);
|
||||
$image->setImageUnits(imagick::RESOLUTION_PIXELSPERCENTIMETER);
|
||||
$image->setimagematte(true);
|
||||
|
||||
// Initializing the layer image height before resizing
|
||||
$before = $image->getImageHeight();
|
||||
|
||||
// Resizing the layer image
|
||||
$image->adaptiveResizeImage((int) round($blank['width'] * $layer['scale']), 0);
|
||||
|
||||
if (!empty($layer['corners'])) {
|
||||
// Received the layer image corners
|
||||
|
||||
// Masking the layer image with corners
|
||||
$image->roundCornersImage($layer['corners'], $layer['corners']);
|
||||
}
|
||||
|
||||
// Calculating the layer image coordinates by the layer image mask
|
||||
$vertical = $blank['height'] - $before;
|
||||
$layer['x'] = (int) round($layer['x'] * $ratio['width'] + ($blank['width'] - $image->getImageWidth()) / 2);
|
||||
$layer['y'] = (int) round($layer['y'] * $ratio['height'] + ($blank['height'] - $image->getImageHeight() + ($vertical > 0 ? $vertical : 0)) / 2);
|
||||
unset($before, $vertical);
|
||||
|
||||
// Compositing the layer image mask with the layer image
|
||||
$image->compositeImage(
|
||||
$mask,
|
||||
imagick::COMPOSITE_DSTIN,
|
||||
(int) round(-$layer['x']),
|
||||
(int) round(-$layer['y'])
|
||||
);
|
||||
|
||||
// Drawing the cutting line
|
||||
$draw = new imagick_draw();
|
||||
$draw->setfillcolor($canvas['background'] ?? '#fff');
|
||||
$stroke = 2;
|
||||
$draw->setStrokeOpacity(1);
|
||||
$draw->setStrokeColor('#000');
|
||||
$draw->setStrokeWidth($stroke);
|
||||
$draw->circle(
|
||||
$place['x'] + $blank['width'] / 2,
|
||||
$place['y'] + $blank['height'] / 2,
|
||||
round($place['x'] + $blank['width'] / 2 + $stroke),
|
||||
round($place['y'] + $blank['height'] + $stroke)
|
||||
);
|
||||
$paper->drawimage($draw);
|
||||
|
||||
// Compositing the layer image with the paper
|
||||
$paper->compositeImage(
|
||||
$image,
|
||||
$image->getImageCompose(),
|
||||
(int) round($place['x'] + $layer['x']),
|
||||
(int) round($place['y'] + $layer['y'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Writing the paper file
|
||||
$paper->writeImage(INDEX . DIRECTORY_SEPARATOR . 'test.jpg');
|
||||
}
|
||||
|
||||
|
||||
// Exit (success)
|
||||
return [];
|
||||
}
|
||||
}
|
||||
132
svoboda/pechatalka/system/models/product.php
Normal file
132
svoboda/pechatalka/system/models/product.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\core,
|
||||
svoboda\pechatalka\models\enumerations\product\type as product_type;
|
||||
|
||||
// Svoboda time
|
||||
use svoboda\time\statement as svoboda;
|
||||
|
||||
// Baza database
|
||||
use mirzaev\baza\database,
|
||||
mirzaev\baza\column,
|
||||
mirzaev\baza\record,
|
||||
mirzaev\baza\enumerations\encoding,
|
||||
mirzaev\baza\enumerations\type;
|
||||
|
||||
// Active Record pattern
|
||||
use mirzaev\record\interfaces\record as record_interface,
|
||||
mirzaev\record\traits\record as record_trait;
|
||||
|
||||
|
||||
// Framework for Telegram
|
||||
use Zanzara\Telegram\Type\User as telegram;
|
||||
|
||||
// Built-in libraries
|
||||
use Exception as exception,
|
||||
RuntimeException as exception_runtime;
|
||||
|
||||
/**
|
||||
* Product
|
||||
*
|
||||
* @package svoboda\pechatalka\models
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class product extends core implements record_interface
|
||||
{
|
||||
use record_trait;
|
||||
|
||||
/**
|
||||
* File
|
||||
*
|
||||
* @var string $database Path to the database file
|
||||
*/
|
||||
protected string $file = DATABASES . DIRECTORY_SEPARATOR . 'products.baza';
|
||||
|
||||
/**
|
||||
* Database
|
||||
*
|
||||
* @method record|null $record The record
|
||||
*
|
||||
* @var database $database The database
|
||||
*/
|
||||
public protected(set) database $database;
|
||||
|
||||
/**
|
||||
* Serialized
|
||||
*
|
||||
* @var bool $serialized Is the implementator object serialized?
|
||||
*/
|
||||
private bool $serialized = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(?record $record = null)
|
||||
{
|
||||
// Initializing the database
|
||||
$this->database = new database()
|
||||
->encoding(encoding::utf8)
|
||||
->columns(
|
||||
new column('identifier', type::integer_unsigned),
|
||||
new column('account', type::integer_unsigned),
|
||||
new column('type', type::string, ['length' => 32]),
|
||||
new column('layers', type::string, ['length' => 4096]),
|
||||
new column('canvas', type::string, ['length' => 4096]),
|
||||
new column('updated', type::integer_unsigned),
|
||||
new column('created', type::integer_unsigned)
|
||||
)
|
||||
->connect($this->file);
|
||||
|
||||
// Initializing the record
|
||||
$record instanceof record and $this->record = $record;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create
|
||||
*
|
||||
* @param int $account The account identifier
|
||||
* @param string|product_type $type The product type
|
||||
* @param string|array $layers The product layers (JSON)
|
||||
* @param string|array $canvas The product canvas (JSON)
|
||||
*
|
||||
* @return int|false The instance, if created
|
||||
*/
|
||||
public function create(
|
||||
int $account,
|
||||
string|product_type $type,
|
||||
string|array $layers,
|
||||
string|array|null $canvas = null
|
||||
): static|false
|
||||
{
|
||||
// Initializing the identifier
|
||||
$identifier = $this->database->count() + 1;
|
||||
|
||||
// Initializing the record
|
||||
$record = $this->database->record(
|
||||
$identifier,
|
||||
$account,
|
||||
$type instanceof product_type ? $type->name : $type,
|
||||
is_string($layers) && json_validate($layers, depth: 16) ? $layers : json_encode($layers, depth: 16),
|
||||
is_string($canvas) && json_validate($canvas, depth: 16) ? $canvas : json_encode($canvas, depth: 16),
|
||||
svoboda::timestamp(),
|
||||
svoboda::timestamp()
|
||||
);
|
||||
|
||||
// Writing the record into the database
|
||||
$created = $this->database->write($record);
|
||||
|
||||
// Exit (success)
|
||||
return $record ? new static(record: $record) : false;
|
||||
}
|
||||
}
|
||||
|
||||
33
svoboda/pechatalka/system/models/telegram/account.php
Normal file
33
svoboda/pechatalka/system/models/telegram/account.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models\telegram;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\core,
|
||||
svoboda\pechatalka\models\account as model,
|
||||
svoboda\pechatalka\models\enumerations\language;
|
||||
|
||||
// Framework for Telegram
|
||||
use Zanzara\Context as context,
|
||||
Zanzara\Telegram\Type\Message as message;
|
||||
|
||||
// Baza database
|
||||
use mirzaev\baza\record;
|
||||
|
||||
// Built-in libraries
|
||||
use Error as error;
|
||||
|
||||
/**
|
||||
* Telegram account
|
||||
*
|
||||
* @package svoboda\pechatalka\models\telegram
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class account extends core
|
||||
{
|
||||
}
|
||||
|
||||
533
svoboda/pechatalka/system/models/telegram/commands.php
Normal file
533
svoboda/pechatalka/system/models/telegram/commands.php
Normal file
@@ -0,0 +1,533 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models\telegram;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\core,
|
||||
svoboda\pechatalka\models\account,
|
||||
svoboda\pechatalka\models\distribution,
|
||||
svoboda\pechatalka\models\member,
|
||||
svoboda\pechatalka\models\telegram\processes\language\select as process_language_select,
|
||||
svoboda\pechatalka\models\enumerations\language;
|
||||
|
||||
// Framework for Telegram
|
||||
use Zanzara\Context as context,
|
||||
Zanzara\Telegram\Type\Message as message,
|
||||
Zanzara\Telegram\Type\Input\InputFile as file_input;
|
||||
|
||||
// Baza database
|
||||
use mirzaev\baza\record;
|
||||
|
||||
/**
|
||||
* Telegram commands
|
||||
*
|
||||
* @package svoboda\pechatalka\models\telegram
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class commands extends core
|
||||
{
|
||||
/**
|
||||
* Menu
|
||||
*
|
||||
* Responce for the commands: "/start", '/menu'
|
||||
*
|
||||
* @param context $context Request data from Telegram
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function menu(context $context): void
|
||||
{
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
// Initializing localization
|
||||
$localization = $context->get('localization');
|
||||
|
||||
if ($localization) {
|
||||
// Initialized localization
|
||||
|
||||
// Initializing the title
|
||||
$title = '📋 *' . $localization['menu_title'] . '*';
|
||||
|
||||
// Initializing accounts
|
||||
$accounts = '*' . $localization['menu_accounts'] . ':* ' . ((new account)->database->count() ?? 0);
|
||||
|
||||
// Initializing the data syncronization for the message
|
||||
$syncronization = '⛓️💥 ' . $localization['menu_not_syncronized'];
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage(
|
||||
<<<TXT
|
||||
$title
|
||||
|
||||
$accounts
|
||||
|
||||
$syncronization
|
||||
TXT,
|
||||
[
|
||||
'reply_markup' => [
|
||||
'inline_keyboard' => [
|
||||
[
|
||||
[
|
||||
'text' => '🔘 ' . $localization['menu_button_generator_pin'],
|
||||
'web_app' => [
|
||||
'url' => 'https://pechatalka.svoboda.works/generator/pin'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
'disable_notification' => true,
|
||||
'remove_keyboard' => true
|
||||
],
|
||||
]
|
||||
)
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
});
|
||||
} else {
|
||||
// Not initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Account
|
||||
*
|
||||
* Responce for the command: "/account"
|
||||
*
|
||||
* Sends information about account with menu
|
||||
*
|
||||
* @param context $context Request data from Telegram
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function account(context $context): void
|
||||
{
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
// Initializing localization
|
||||
$localization = $context->get('localization');
|
||||
|
||||
if ($localization) {
|
||||
// Initialized localization
|
||||
|
||||
// Initializing title for the message
|
||||
$title = '🫵 ' . $localization['account_title'];
|
||||
|
||||
// Declaring buufer of rows about authorizations
|
||||
$authorizations = '';
|
||||
|
||||
// Initializing rows about authorization
|
||||
foreach ($account->values() as $key => $value) {
|
||||
// Iterating over account parameters
|
||||
|
||||
if (str_starts_with($key, 'authorized_')) {
|
||||
// Iterating over account authorizations
|
||||
|
||||
// Skipping system authorizations
|
||||
if (str_starts_with($key, 'authorized_system_')) continue;
|
||||
|
||||
// Writing into buffer of rows about authorizations
|
||||
$authorizations .= ($value ? '✅' : '❎') . ' *' . ($localization["account_$key"] ?? $key) . ':* ' . ($value ? $localization['yes'] : $localization['no']) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Trimming the last line break character
|
||||
$authorizations = trim($authorizations, "\n");
|
||||
|
||||
// Initializing the data export for the message
|
||||
$export = '📤 ' . $localization['account_export'];
|
||||
|
||||
// Initializing the data security for the message
|
||||
$data = $localization['account_data'];
|
||||
|
||||
// Initializing the data security repository for the message
|
||||
$security = '📁 [' . $localization['account_security_repository'] . '](https://git.svoboda.works/mirzaev/security) \([' . $localization['account_security_repository_mirror_github'] . '](https://github.com/mature-woman/security)\)';
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage(
|
||||
<<<TXT
|
||||
$title
|
||||
|
||||
$authorizations
|
||||
|
||||
$export
|
||||
|
||||
$data
|
||||
|
||||
$security
|
||||
TXT,
|
||||
[
|
||||
'reply_markup' => [
|
||||
'remove_keyboard' => true,
|
||||
'disable_notification' => true
|
||||
],
|
||||
'link_preview_options' => [
|
||||
'is_disabled' => true
|
||||
]
|
||||
]
|
||||
);
|
||||
} else {
|
||||
// Not initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Language
|
||||
*
|
||||
* Responce for the command: "/language"
|
||||
*
|
||||
* Send the language selection menu
|
||||
*
|
||||
* @param context $context Request data from Telegram
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function language(context $context): void
|
||||
{
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
// Initializing language
|
||||
$language = $context->get('language');
|
||||
|
||||
if ($language instanceof language) {
|
||||
// Initialized language
|
||||
|
||||
// Initializing localization
|
||||
$localization = $context->get('localization');
|
||||
|
||||
if ($localization) {
|
||||
// Initialized localization
|
||||
|
||||
// Sending the language selection
|
||||
process_language_select::menu(
|
||||
context: $context,
|
||||
prefix: 'settings_language_',
|
||||
title: '🌏 *' . $localization['settings_select_language_title'] . '*',
|
||||
description: '🌏 *' . $localization['settings_select_language_description'] . '*'
|
||||
);
|
||||
} else {
|
||||
// Not initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized language
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize language*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Repository
|
||||
*
|
||||
* Responce for the command: "/repository"
|
||||
*
|
||||
* Sends information about project and menu
|
||||
*
|
||||
* @param context $context Request data from Telegram
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function repository(context $context): void
|
||||
{
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
// Initializing localization
|
||||
$localization = $context->get('localization');
|
||||
|
||||
if ($localization) {
|
||||
// Initialized localization
|
||||
|
||||
// Initializing title of the message
|
||||
$title = '🏛️ ' . $localization['repository_title'];
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage($title . "\n\n" . $localization['repository_text'], [
|
||||
'reply_markup' => [
|
||||
'inline_keyboard' => [
|
||||
[
|
||||
[
|
||||
'text' => '🏛️ ' . $localization['repository_button_code'],
|
||||
'url' => 'https://git.mirzaev.sexy/svoboda/pechatalka'
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
'text' => '⚠️ ' . $localization['repository_button_issues'],
|
||||
'url' => 'https://git.mirzaev.sexy/svoboda/pechatalka/issues'
|
||||
],
|
||||
[
|
||||
'text' => '🌱 ' . $localization['repository_button_suggestions'],
|
||||
'url' => 'https://git.mirzaev.sexy/svoboda/pechatalka/issues'
|
||||
]
|
||||
]
|
||||
],
|
||||
'remove_keyboard' => true,
|
||||
'disable_notification' => true
|
||||
],
|
||||
'link_preview_options' => [
|
||||
'is_disabled' => true
|
||||
]
|
||||
]);
|
||||
} else {
|
||||
// Not initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Author
|
||||
*
|
||||
* Responce for the command: "/author"
|
||||
*
|
||||
* Sends
|
||||
*
|
||||
* @param context $context Request data from Telegram
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function author(context $context): void
|
||||
{
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
// Initializing localization
|
||||
$localization = $context->get('localization');
|
||||
|
||||
if ($localization) {
|
||||
// Initialized localization
|
||||
|
||||
// Initializing title of the message
|
||||
$title = '👽 ' . $localization['author_title'];
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage($title . "\n\n" . $localization['author_text'], [
|
||||
'reply_markup' => [
|
||||
'inline_keyboard' => [
|
||||
[
|
||||
[
|
||||
'text' => '📚 ' . $localization['author_button_neurojournal'],
|
||||
'url' => 'https://mirzaev.sexy'
|
||||
],
|
||||
[
|
||||
'text' => '🤟 ' . $localization['author_button_projects'],
|
||||
'url' => 'https://git.svoboda.works/mirzaev?tab=activity'
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
'text' => '📣 ' . $localization['author_button_telegram'],
|
||||
'url' => 'https://t.me/blog_mirzaev_sexy'
|
||||
],
|
||||
[
|
||||
'text' => '✖️ ' . $localization['author_button_twitter'],
|
||||
'url' => 'https://x.com/mirzaev_sexy'
|
||||
],
|
||||
[
|
||||
'text' => '🦋 ' . $localization['author_button_bluesky'],
|
||||
'url' => 'https://bsky.app/profile/mirzaev.bsky.social'
|
||||
],
|
||||
[
|
||||
'text' => '⛓️ ' . $localization['author_button_bastyon'],
|
||||
'url' => 'https://bsky.app/profile/mirzaev.bsky.social'
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
'text' => '🇺🇸 ' . $localization['author_button_youtube_english'],
|
||||
'url' => 'https://www.youtube.com/@MIRZAEV'
|
||||
],
|
||||
[
|
||||
'text' => '🇷🇺 ' . $localization['author_button_youtube_russian'],
|
||||
'url' => 'https://www.youtube.com/@MIRZAEV'
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
'text' => '✉️ ' . $localization['author_button_message'],
|
||||
'url' => 'https://t.me/mirzaev_sexy'
|
||||
]
|
||||
]
|
||||
],
|
||||
'remove_keyboard' => true,
|
||||
'disable_notification' => true
|
||||
],
|
||||
'link_preview_options' => [
|
||||
'is_disabled' => true
|
||||
]
|
||||
]);
|
||||
} else {
|
||||
// Not initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Society
|
||||
*
|
||||
* Responce for the command: "/society"
|
||||
*
|
||||
* Sends the "mushroom" image and the localized text "why so shroomious"
|
||||
*
|
||||
* @param context $context Request data from Telegram
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function society(context $context): void
|
||||
{
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
// Initializing localization
|
||||
$localization = $context->get('localization');
|
||||
|
||||
if ($localization) {
|
||||
// Initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendPhoto(
|
||||
new file_input(STORAGE . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'mushroom.jpg'),
|
||||
[
|
||||
'caption' => $localization['why_so_shroomious'],
|
||||
'disable_notification' => true
|
||||
]
|
||||
);
|
||||
} else {
|
||||
// Not initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
372
svoboda/pechatalka/system/models/telegram/middlewares.php
Normal file
372
svoboda/pechatalka/system/models/telegram/middlewares.php
Normal file
@@ -0,0 +1,372 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models\telegram;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\core,
|
||||
svoboda\pechatalka\models\account,
|
||||
svoboda\pechatalka\models\enumerations\language;
|
||||
|
||||
// Framework for Telegram
|
||||
use Zanzara\Context as context,
|
||||
Zanzara\Telegram\Type\Message as message,
|
||||
Zanzara\Middleware\MiddlewareNode as node;
|
||||
|
||||
// Baza database
|
||||
use mirzaev\baza\record;
|
||||
|
||||
// Built-in libraries
|
||||
use Error as error;
|
||||
|
||||
/**
|
||||
* Telegram middlewares
|
||||
*
|
||||
* @package svoboda\pechatalka\models\telegram
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class middlewares extends core
|
||||
{
|
||||
/**
|
||||
* Account (middleware)
|
||||
*
|
||||
* Initialize or registrate the account and write it to the `account` variable inside the `$context`
|
||||
*
|
||||
* @param context $context
|
||||
* @param node $next
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function account(context $context, node $next): void
|
||||
{
|
||||
// Is the process stopped?
|
||||
if ($context->get('stop')) return;
|
||||
|
||||
// Initializing the telegram account
|
||||
$telegram = $context->getEffectiveUser();
|
||||
|
||||
// Initializing the account
|
||||
/* $account = new account()->initialize($telegram); */
|
||||
$account = (new account())->initialize($telegram);
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
// Writing the account into the context variable
|
||||
$context->set('account', $account);
|
||||
|
||||
// Continuation of the process
|
||||
$next($context);
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Language (middleware)
|
||||
*
|
||||
* Implement the account language
|
||||
*
|
||||
* @param context $context
|
||||
* @param node $next
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function language(context $context, node $next): void
|
||||
{
|
||||
// Is the process stopped?
|
||||
if ($context->get('stop')) return;
|
||||
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
if ($account->language) {
|
||||
// Initialized the language parameter
|
||||
|
||||
try {
|
||||
// Writing the account language into the context variable
|
||||
$context->set('language', language::{$account->language});
|
||||
} catch (error $error) {
|
||||
// Not initialized the language
|
||||
|
||||
// Writing the default language into the context variable
|
||||
$context->set('language', language::en);
|
||||
}
|
||||
} else {
|
||||
// Not initialized the language parameter
|
||||
|
||||
// Writing the default language into the context variable
|
||||
$context->set('language', language::en);
|
||||
}
|
||||
|
||||
// Continuation of the process
|
||||
$next($context);
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Localization (middleware)
|
||||
*
|
||||
* Implement the account language and initialize the localization file
|
||||
*
|
||||
* @param context $context
|
||||
* @param node $next
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function localization(context $context, node $next): void
|
||||
{
|
||||
// Is the process stopped?
|
||||
if ($context->get('stop')) return;
|
||||
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
// Initializing the language
|
||||
$language = $context->get('language');
|
||||
|
||||
if ($language instanceof language) {
|
||||
// Initialized the language
|
||||
|
||||
// Initializing path to the localization file
|
||||
$file = LOCALIZATIONS . DIRECTORY_SEPARATOR . strtolower($language->label()) . '.php';
|
||||
|
||||
if (file_exists($file) && is_readable($file)) {
|
||||
// Found the localization file
|
||||
|
||||
// Initializing localization
|
||||
$localization = require($file);
|
||||
|
||||
if (is_array($localization)) {
|
||||
// Initialized localization
|
||||
|
||||
// Writing localization into the context variable
|
||||
$context->set('localization', $localization);
|
||||
|
||||
// Continuation of the process
|
||||
$next($context);
|
||||
} else {
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not found the localization file
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize the localization file*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized language
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize language*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings (middleware)
|
||||
*
|
||||
* Check the account for access to the settings
|
||||
*
|
||||
* @param context $context
|
||||
* @param node $next
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function settings(context $context, node $next): void
|
||||
{
|
||||
// Is the process stopped?
|
||||
if ($context->get('stop')) return;
|
||||
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
if ($account->authorized_settings) {
|
||||
// Authorized the account to the settings
|
||||
|
||||
// Continuation of the process
|
||||
$next($context);
|
||||
} else {
|
||||
// Not authorized the account to the settings
|
||||
|
||||
// Initializing localization
|
||||
$localization = $context->get('localization');
|
||||
|
||||
if ($localization) {
|
||||
// Initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⛔ *' . $localization['not_authorized_settings'] . '*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
|
||||
// Stopping the process
|
||||
$context->set('stop', true);
|
||||
} else {
|
||||
// Not initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* System settings (middleware)
|
||||
*
|
||||
* Check the account for access to the system settings
|
||||
*
|
||||
* @param context $context
|
||||
* @param node $next
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function system_settings(context $context, node $next): void
|
||||
{
|
||||
// Is the process stopped?
|
||||
if ($context->get('stop')) return;
|
||||
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
if ($account->authorized_system_settings) {
|
||||
// Authorized the account to the system settings
|
||||
|
||||
// Continuation of the process
|
||||
$next($context);
|
||||
} else {
|
||||
// Not authorized the account to the system settings
|
||||
|
||||
// Initializing localization
|
||||
$localization = $context->get('localization');
|
||||
|
||||
if ($localization) {
|
||||
// Initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⛔ *' . $localization['not_authorized_system_settings'] . '*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
|
||||
// Stopping the process
|
||||
$context->set('stop', true);
|
||||
} else {
|
||||
// Not initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models\telegram\processes\language;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\core,
|
||||
svoboda\pechatalka\models\enumerations\language;
|
||||
|
||||
// Framework for Telegram
|
||||
use Zanzara\Context as context,
|
||||
Zanzara\Telegram\Type\Message as message;
|
||||
|
||||
// Baza database
|
||||
use mirzaev\baza\record;
|
||||
|
||||
/**
|
||||
* Telegram language select
|
||||
*
|
||||
* @package svoboda\pechatalka\models\telegram\processes\language
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class select extends core
|
||||
{
|
||||
/**
|
||||
* Language
|
||||
*
|
||||
* Send the language choose menu
|
||||
*
|
||||
* @param context $context Request data from Telegram
|
||||
* @param string $prefix Prefix for 'callback_data' (`$prefix . $language->name`)
|
||||
* @param string $title Title of the message
|
||||
* @param string $description Description of the message
|
||||
* @param array $exclude Languages that will be excluded ['ru', 'en'...]
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function menu(context $context, string $prefix, string $title, string $description, array $exclude = []): void
|
||||
{
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
// Initializing language
|
||||
$language = $context->get('language');
|
||||
|
||||
if ($language) {
|
||||
// Initialized language
|
||||
|
||||
// Initializing localization
|
||||
$localization = $context->get('localization');
|
||||
|
||||
if ($localization) {
|
||||
// Initialized localization
|
||||
|
||||
// Declaring the buffer of generated keyboard with languages
|
||||
$keyboard = [];
|
||||
|
||||
// Initializing the iterator of rows
|
||||
$row = 0;
|
||||
|
||||
// Initializing buffer of languages
|
||||
$languages = language::cases();
|
||||
|
||||
// Deleting the actual language from buffer of languages
|
||||
unset($languages[array_search($language, $languages, strict: true)]);
|
||||
|
||||
// Sorting buffer of languages by the actual language
|
||||
$languages = [$language, ...$languages];
|
||||
|
||||
foreach ($languages as $language) {
|
||||
// Iterating over languages
|
||||
|
||||
// Skipping excluded languages
|
||||
if (array_search($language->name, $exclude, strict: true) !== false) continue;
|
||||
|
||||
// Initializing the row
|
||||
$keyboard[$row] ??= [];
|
||||
|
||||
// Writing the language choose button into the buffer of generated keyboard with languages
|
||||
$keyboard[$row][] = [
|
||||
'text' => ($language->flag() ? $language->flag() . ' ' : '') . $language->label($language),
|
||||
'callback_data' => $prefix . $language->name
|
||||
];
|
||||
|
||||
// When reaching 4 buttons in a row, move to the next row
|
||||
if (count($keyboard[$row]) === 4) ++$row;
|
||||
}
|
||||
|
||||
// Writing the button for helping lozalizing
|
||||
$keyboard[$row === 0 && empty($keyboard[0]) ? 0 : ++$row] = [
|
||||
[
|
||||
'text' => '🗂 ' . $localization['select_language_button_add'],
|
||||
'url' => 'https://git.svoboda.works/svoboda/pechatalka/src/branch/stable/svoboda/pechatalka/system/localizations'
|
||||
]
|
||||
];
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage(
|
||||
$title ?? '🌏 *' . $localization['select_language_title'] . "*\n" . ($description ?? $localization['select_language_description']),
|
||||
[
|
||||
'reply_markup' => [
|
||||
'inline_keyboard' => $keyboard,
|
||||
'disable_notification' => true
|
||||
],
|
||||
]
|
||||
);
|
||||
} else {
|
||||
// Not initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized language
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize language*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Sended the message
|
||||
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
157
svoboda/pechatalka/system/models/telegram/settings.php
Normal file
157
svoboda/pechatalka/system/models/telegram/settings.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace svoboda\pechatalka\models\telegram;
|
||||
|
||||
// Files of the project
|
||||
use svoboda\pechatalka\models\core,
|
||||
svoboda\pechatalka\models\account,
|
||||
svoboda\pechatalka\models\enumerations\language,
|
||||
svoboda\pechatalka\models\telegram\middlewares;
|
||||
|
||||
// Framework for Telegram
|
||||
use Zanzara\Zanzara,
|
||||
Zanzara\Context as context,
|
||||
Zanzara\Telegram\Type\Message as message,
|
||||
Zanzara\Middleware\MiddlewareNode as node;
|
||||
|
||||
// Baza database
|
||||
use mirzaev\baza\record;
|
||||
|
||||
// Built-in libraries
|
||||
use Error as error;
|
||||
|
||||
/**
|
||||
* Telegram settings
|
||||
*
|
||||
* @package svoboda\pechatalka\models\telegram
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
*/
|
||||
final class settings extends core
|
||||
{
|
||||
/**
|
||||
* Language
|
||||
*
|
||||
* Write language into the account record
|
||||
*
|
||||
* @param context $context Request data from Telegram
|
||||
* @param language $language The language
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function language(context $context, language $language): void
|
||||
{
|
||||
// Initializing the account
|
||||
$account = $context->get('account');
|
||||
|
||||
if ($account instanceof record) {
|
||||
// Initialized the account
|
||||
|
||||
// Initializing localization
|
||||
$localization = $context->get('localization');
|
||||
|
||||
if ($localization) {
|
||||
// Initialized localization
|
||||
|
||||
// Initializing the account model
|
||||
$model = new account();
|
||||
|
||||
// Updating the account in the database
|
||||
$updated = $model->database->read(
|
||||
filter: fn(record $record) => $record->identifier === $account->identifier,
|
||||
update: function (record &$record) use ($language) {
|
||||
// Writing new language value into the record
|
||||
$record->language = $language->name;
|
||||
},
|
||||
amount: 1
|
||||
)[0] ?? null;
|
||||
|
||||
if ($updated instanceof record) {
|
||||
// Updated the account in the database
|
||||
|
||||
// Writing the updated account into the context variable
|
||||
$context->set('account', $updated);
|
||||
|
||||
middlewares::language($context, new node(function (context $context) use ($account, $updated) {
|
||||
// Updated language
|
||||
|
||||
middlewares::localization($context, new node(function (context $context) use ($account, $updated) {
|
||||
// Updated localization
|
||||
|
||||
// Initializing localization
|
||||
$localization = $context->get('localization');
|
||||
|
||||
if ($localization) {
|
||||
// Initialized localization
|
||||
|
||||
try {
|
||||
// Initializing the old language
|
||||
$old = language::{$account->language};
|
||||
|
||||
// Initializing the new language
|
||||
$new = language::{$updated->language};
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('✅ *' . $localization['settings_language_update_success'] . '* ' . ($old->flag() ? $old->flag() . ' ' : '') . $old->label($new) . ' → *' . ($new->flag() ? $new->flag() . ' ' : '') . $new->label($new) . '*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
} catch (error $error) {
|
||||
// Failed to send the message about language update
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('❎ *' . $localization['settings_language_update_fail'])
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}));
|
||||
}));
|
||||
} else {
|
||||
// Not updated the account in the database
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('❎ *' . $localization['settings_language_update_fail'])
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized localization
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize localization*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not initialized the account
|
||||
|
||||
// Sending the message
|
||||
$context->sendMessage('⚠️ *Failed to initialize your Telegram account*')
|
||||
->then(function (message $message) use ($context) {
|
||||
// Ending the conversation process
|
||||
$context->endConversation();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace mirzaev\pechatalka\models\traits;
|
||||
namespace svoboda\pechatalka\models\traits;
|
||||
|
||||
// Built-in libraries
|
||||
use exception;
|
||||
@@ -14,7 +14,7 @@ use exception;
|
||||
*
|
||||
* @method static void delete(string $directory, array &$errors)
|
||||
*
|
||||
* @package mirzaev\pechatalka\models\traits
|
||||
* @package svoboda\pechatalka\models\traits
|
||||
*
|
||||
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||
8
svoboda/pechatalka/system/public/css/fonts/cascadia_code.css
Executable file
8
svoboda/pechatalka/system/public/css/fonts/cascadia_code.css
Executable file
@@ -0,0 +1,8 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
@font-face {
|
||||
font-family: 'Cascadia Code';
|
||||
src: url("/fonts/cascadia_code/CascadiaCode.woff2");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
7
svoboda/pechatalka/system/public/css/fonts/commissioner.css
Executable file
7
svoboda/pechatalka/system/public/css/fonts/commissioner.css
Executable file
@@ -0,0 +1,7 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
@font-face {
|
||||
font-family: 'Commissioner';
|
||||
src: url('/fonts/commissioner/commissioner.ttf');
|
||||
font-weight: 400;
|
||||
}
|
||||
65
svoboda/pechatalka/system/public/css/fonts/geologica.css
Executable file
65
svoboda/pechatalka/system/public/css/fonts/geologica.css
Executable file
@@ -0,0 +1,65 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geologica';
|
||||
src: url("/fonts/geologica/Geologica-Thin.ttf");
|
||||
font-weight: 100;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geologica';
|
||||
src: url("/fonts/geologica/Geologica_Auto-ExtraLight.ttf");
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geologica';
|
||||
src: url("/fonts/geologica/Geologica-Light.ttf");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geologica';
|
||||
src: url("/fonts/geologica/Geologica-Regular.ttf");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geologica';
|
||||
src: url("/fonts/geologica/Geologica-Medium.ttf");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geologica';
|
||||
src: url("/fonts/geologica/Geologica-SemiBold.ttf");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geologica';
|
||||
src: url("/fonts/geologica/Geologica-Bold.ttf");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geologica';
|
||||
src: url("/fonts/geologica/Geologica-ExtraBold.ttf");
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geologica';
|
||||
src: url("/fonts/geologica/Geologica-Black.ttf");
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user