369 lines
14 KiB
Markdown
Executable File
369 lines
14 KiB
Markdown
Executable File
# huesos
|
|
Base for creating shop chat-robots using Web App technology for [Telegram](https://telegram.org)
|
|
|
|
## Functions
|
|
1. Tree-structured catalog
|
|
2. Product cards with images carousel ([mirzaev/hotline.mjs](https://git.svoboda.works/mirzaev/hotline.mjs))
|
|
3. Cart (CRUD with limits and session binding)
|
|
4. Saving user data (and session) for all devices
|
|
5. Deliveries settings (with interactive maps and automatic geolocation detection on smartphones)
|
|
6. Real time price generation
|
|
7. Interface according to all Telegram standards
|
|
8. Public offer, dynamic settings and suspensions
|
|
9. Multi-language and easy to add new languages
|
|
10. Multi-currency and easy to add new currencies
|
|
11. Loading products and categories from an excel-file with automatic updating of existing ones
|
|
12. Flag authorization system, separate access for testers
|
|
13. Sending the generated order directly to the chat-robot
|
|
14. Intelligent search by titles, descriptions and other parameters (Levenshtein algorithm + separate settings for different languages)
|
|
15. Asynchronous chat-robot and Web App based on dynamic queries (AJAX)
|
|
16. Modern non-relational database ready for scaling and integration with third-party CRM
|
|
17. Fully documented code in English
|
|
18. Customizable menu buttons
|
|
19. Responsive design with built-in Telegram buttons and haptic functions
|
|
20. Automatic download and compression of images in 4 sizes (currently only from Yandex.Disk, but the system is ready to add new sources)
|
|
21. Commercially approved fonts and pure CSS icons
|
|
22. Product filter panel using pure CSS
|
|
23. Damper technology on all user interaction functions ([mirzaev/damper.mjs](https://git.svoboda.works/mirzaev/damper.mjs))
|
|
24. Two-step registration system (entering other data after creating an order)
|
|
25. Delivery company selection system (ready for scaling)
|
|
26. Acquiring company selection system (ready for scaling)
|
|
27. Sending paid orders to the operators chat with the customer contacts
|
|
|
|
## Integrations
|
|
|
|
### Import
|
|
*Methods for importing products into the shop*<br>
|
|
1. Excel-file (products and categories)
|
|
|
|
### Images download
|
|
*Methods of transferring images when importing products into the shop*<br>
|
|
1. [Yandex.Disk](https://360.yandex.ru/disk/) (russian) ([API](https://yandex.com/dev/disk/))
|
|
|
|
### Delivery companies
|
|
*Companies that deliver products from the shop*<br>
|
|
1. [CDEK](https://www.cdek.ru/) (russian) ([API](https://api-docs.cdek.ru/29923741.html)) ([PHP library](https://github.com/TTATPuOT/cdek-sdk2.0))
|
|
|
|
### Acquiring companies
|
|
*Companies that provide acquiring for the shop*<br>
|
|
1. [Robokassa](https://robokassa.com) (russian) (no swift) ([API](https://docs.robokassa.ru/pay-interface/))
|
|
|
|
## Dependencies
|
|
1. [PHP 8.4](https://www.php.net/releases/8.4/en.php)
|
|
2. [Composer](https://getcomposer.org/) (php package manager)
|
|
3. [MINIMAL](https://git.svoboda.works/mirzaev/minimal) (PHP framework)
|
|
4. [Twig](https://twig.symfony.com/) (HTML templater)
|
|
5. [Zanzara](https://github.com/badfarm/zanzara) (Telegram framework + ReactPHP)
|
|
6. [ArangoDB](https://docs.arangodb.com/3.11/about-arangodb/) (non-relational database)
|
|
7. [NGINX](https://nginx.org/en/) (web server) *(can be replaced)*
|
|
8. [SystemD](https://systemd.io/) (service manager) *(can be replaced)*
|
|
|
|
<small>You can find other dependencies in the file `/composer.json`</small>
|
|
|
|
## Installation
|
|
|
|
### AnangoDB
|
|
|
|
1. **Configure unix-socket**<br>
|
|
|
|
Edit the file `/etc/arangodb3/arangod.conf`<br>
|
|
`endpoint = tcp://127.0.0.1:8529` -> `endpoint = unix:///var/run/arangodb3/arango.sock` (this will disable the web panel)<br>
|
|
<br>
|
|
To make the web panel work, you can add this to the NGINX server settings:
|
|
```lua
|
|
server {
|
|
...
|
|
|
|
server_name arangodb.domain.zone;
|
|
|
|
...
|
|
|
|
allow YOUR_IP_ADDRESS;
|
|
allow 192.168.1.1/24;
|
|
allow 127.0.0.1;
|
|
deny all;
|
|
|
|
# ArangoDB
|
|
location / {
|
|
proxy_pass http://arangodb;
|
|
}
|
|
}
|
|
|
|
upstream arangodb {
|
|
server unix:/var/run/arangodb3/arango.sock;
|
|
}
|
|
```
|
|
[here is my solution for "permission denied" problem on Ubuntu (accepted by ArangoDB maintainer)](https://github.com/arangodb/arangodb/issues/17302)<br>
|
|
|
|
1. **Configure TCP (instead of unix-socket)**<br>
|
|
|
|
Edit the file `/etc/arangodb3/arangod.conf`<br>
|
|
`endpoint = tcp://127.0.0.1:8529` -> `endpoint = tcp://0.0.0.0:8529`<br>
|
|
|
|
Edit the file `mirzaev/huesos/system/settings/arangodb.php`<br>
|
|
`unix:///var/run/arangodb3/arango.sock` -> `tcp://YOUR_IP_ADDRESS:8529` (it is slow and not secure)
|
|
|
|
---
|
|
|
|
2. **Create a Graph with the specified values**<br>
|
|
**Name:** catalog<br>
|
|
|
|
* Relation 1<br>
|
|
**edgeDefinition:** entry<br>
|
|
**fromCollections:** category, product<br>
|
|
**toCollections:** category
|
|
|
|
* Relation 2<br>
|
|
**edgeDefinition:** reservation<br>
|
|
**fromCollections:** product<br>
|
|
**toCollections:** cart
|
|
|
|
---
|
|
|
|
3. **Create a Graph with the specified values**<br>
|
|
**Name:** users<br>
|
|
|
|
* Relation 1<br>
|
|
**edgeDefinition:** connect<br>
|
|
**fromCollections:** cart, session<br>
|
|
**toCollections:** account, session<br>
|
|
|
|
* Orphan Collections<br>
|
|
product
|
|
|
|
---
|
|
|
|
4. **Create indexes for the "product" collection**<br>
|
|
**Type:** "Inverted Index"<br>
|
|
**Fields:** name.ru<br>
|
|
**Analyzer:** "text_ru"<br>
|
|
**Search field:** true<br>
|
|
**Name:** name_ru<br><br>
|
|
|
|
*Add indexes for all search parameters and for all languages (search language is selected based on the user's language, <br>
|
|
otherwise from the default language specified in the active settings from **settings** collection document)*<br>
|
|
<br>
|
|
*See fields in the `mirzaev/arming_bot/models/product`<br>
|
|
**name.ru**, **description.ru** and **compatibility.ru***<br>
|
|
|
|
---
|
|
|
|
5. **Create a View with the specified values**<br>
|
|
**type:** search-alias (you can also use "arangosearch")<br>
|
|
**name:** **product**s_search<br>
|
|
**indexes:**<br><br>
|
|
|
|
You can copy an example of view file from here: `/examples/arangodb/views/products_search.json`
|
|
|
|
```json
|
|
"indexes": [
|
|
{
|
|
"collection": "product",
|
|
"index": "title_ru" # THIS IS AN EXAMPLE
|
|
}
|
|
]
|
|
```
|
|
|
|
### NGINX
|
|
|
|
1. **Create a NGINX server**<br>
|
|
You can copy an example of server file from here: `/examples/nginx/server.conf`
|
|
|
|
2. **Add support for javascript modules**<br>
|
|
Edit the file `/etc/nginx/mime.types`<br>
|
|
`application/javascript js;` -> `application/javascript js mjs;`
|
|
|
|
3. **Generate a TLS/SSL sertificate** (via [certbot](http://certbot.eff.org/) for [ubuntu](https://ubuntu.com/))<br>
|
|
3.1. `sudo apt install certbot python3-certbot-nginx`<br>
|
|
3.2. `sudo certbot certonly --nginx` (The **domain** must already be **bound** to the **IP-address** of the server by `A-record` or `AAAA-record`)
|
|
|
|
5. **Firewall rules for HTTP and HTTPS** (for [ubuntu](https://ubuntu.com/))<br>
|
|
4.1 `sudo ufw allow "NGINX Full"`<br>
|
|
4.1.1 `sudo ufw allow 22` (make sure that the port for SSH connection is open)<br>
|
|
4.2 `sudo ufw enable`
|
|
|
|
### SystemD (or any alternative you like)
|
|
You can copy an example of systemd file from here: `/examples/systemd/huesos.service`<br>
|
|
1. `sudo cp huesos.service /etc/systemd/system/huesos.service && sudo chmod +x /etc/systemd/system/huesos.service`
|
|
2. `sudo systemctl daemon-reload`
|
|
3. `sudo systemctl enable huesos`<br>
|
|
|
|
*before you execute the command think about **what it does** and whether the **paths** are specified correctly*<br>
|
|
*the configuration file is very simple and you can remake it for any alternative to SystemD that you like*
|
|
|
|
## Menu
|
|
*Menu inside the Web App*<br><br>
|
|
Make sure you have a **menu** collection (can be created automatically)<br>
|
|
You can copy a clean menu documents without comments from here: `/examples/arangodb/collections/menu`
|
|
|
|
```json
|
|
{
|
|
"urn": "/", // Link
|
|
"name": {
|
|
"en": "Main page",
|
|
"ru": "Главная страница"
|
|
},
|
|
"style": { // The `style` attribute
|
|
"order": 0
|
|
},
|
|
"class": "",
|
|
"icon": { // Icon from `/themes/default/css/icons`
|
|
"style": { // The `style` attribute
|
|
"rotate": "-135deg"
|
|
},
|
|
"class": "arrow circle" // Classes of the icon
|
|
},
|
|
"image": { // Image at the background @deprecated?
|
|
"storage": null
|
|
}
|
|
}
|
|
```
|
|
|
|
## Settings
|
|
*Settings of chat-robot and Web App*<br><br>
|
|
Make sure you have a **settings** collection (can be created automatically) and at least one document with the "status" parameter set to "active"<br>
|
|
You can copy a clean settings document without comments from here: `/examples/arangodb/collections/settings.json`
|
|
|
|
```json
|
|
{
|
|
"status": "active", // Values: "active", "inactive" (string) Status of the settings document?
|
|
"project": {
|
|
"name": "PROJECT" // Name of the projext (string)
|
|
},
|
|
"language": "en", // Will be converted to an instance of enumeration `mirzaev\arming_bot\models\enumerations\language`
|
|
"currency": "usd", // Will be converted to an instance of enumeration `mirzaev\arming_bot\models\enumerations\currency`
|
|
"company": {
|
|
"identifier": null, // Example: "000000000000000" (string|null) (if `null` it will not be displayed)
|
|
"tax": null, // Example: "000000000000" (string|null) (if `null` it will not be displayed)
|
|
"name": null, // Example: "COMPANY" (string|null) (if `null` it will not be displayed)
|
|
"offer": false, // Display the data of a public offer in the footer? (bool) (does not affect the `/offer` page generation)
|
|
"sim": null, // Examples: "+7 000 000-00-00", "70000000000" (string|null) (if `null` it will not be displayed)
|
|
"mail": null // Example: "name@domain.zone" (string|null) (if `null` it will not be displayed)
|
|
},
|
|
"search": {
|
|
"enabled": true, // Enable the search input field?
|
|
"position": "fixed" // Values: "fixed", "relative"
|
|
},
|
|
"catalog": {
|
|
"categories": {
|
|
"display": "column", // Values: "row" (flex wrap), "column" (rows) Type of the catalog display
|
|
"structure": "lists", // Values: "pages" (pages with categories and products), "lists" (all categories as tree lists on the main page)
|
|
"buttons": {
|
|
"height": "120px", // Examples: "80px", "120px", "180px" (string|null) Height of buttons
|
|
"background": "#fafafa", // Examples: "#fafafa", "yellow" (string|null) Color of buttons background
|
|
"separator": {
|
|
"enabled": true, // Enable separators?
|
|
"width": "60%" // Exaples: "100%", "80%", "60%" (string|null) Width of separators over images (relative to image width from the left)
|
|
},
|
|
"lists": {
|
|
"height": "800px", // Examples: "500px", "100%" (string|null) Maximum height of lists (`max-height` for animations working)
|
|
"background": null, // Examples: "#fafafa", "yellow" (string|null) Color of lists
|
|
"separator": null, // Examples: "#fafafa", "yellow" (string|null) Color of separators between rows
|
|
"separated": true, // Separate lists from its buttons?
|
|
"blocks": true, // Blocks instead of plain text?
|
|
"arrow": true // Add arrow at the right?
|
|
},
|
|
"texts": {
|
|
"position": {
|
|
"vertical": "center" // Values: "top", "center", "bottom" (string|null) Position of texts of ascendants categories
|
|
},
|
|
"width": "max(8rem, 20%)", // Examples: "60%", "5rem", "max(8rem, 20%)" (string|null) Width of the text section (left side of buttons)
|
|
"background": false, // Enable wrapping element for texts?
|
|
"title": {
|
|
"color": "#020202" // Examples: "#fafafa", "yellow" (string|null) Color of titles
|
|
},
|
|
"description": {
|
|
"color": "#121212" // Examples: "#fafafa", "yellow" (string|null) Color of descriptions
|
|
}
|
|
},
|
|
"images": {
|
|
"filter": "contrast(1.2)" // Example: "contrast(1.2)" (string|null) Filter for images
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"cart": {
|
|
"enabled": true // Enable the cart button?
|
|
},
|
|
"css": {
|
|
"catalog-button-cart-background": "#40a7e3",
|
|
"product-button-cart-background": "#40a7e3"
|
|
"catalog-button-cart-added-background": "#90be36",
|
|
"product-button-cart-added-background": "#90be36"
|
|
},
|
|
"account": {
|
|
"enabled": false // Enable the account section? (works only when opened from telegram `inline-button`)
|
|
},
|
|
"menu": {
|
|
"enabled": true, // Enable the main menu?
|
|
"position": "fixed" // Values: "fixed" (fixed to the bottom as a solid line), "relative" (at the top as separated buttons) (stirng) Position of the main menu
|
|
},
|
|
"header": {
|
|
"enabled": true, // Enable the header?
|
|
"position": "fixed" // Values: "fixed" (fixed to the bottom), "relative" (at the top) (stirng) Position of the header
|
|
},
|
|
"acquirings": {
|
|
"robokassa": {
|
|
"enabled": true, // Enable the Robokassa acquiring?
|
|
"mode": "test" // Values: "work", "test" (string) Mode of the Robokassa acquiring
|
|
}
|
|
},
|
|
"input": {
|
|
"deliveries": {
|
|
"site": [], // Values: "sim", "name", "destination", "address", "commentary"
|
|
"chat": [
|
|
"sim",
|
|
"name",
|
|
"destination",
|
|
"address",
|
|
"commentary"
|
|
] // Values: "sim", "name", "destination", "address", "commentary"
|
|
}
|
|
},
|
|
"deliveries": {
|
|
"cdek": {
|
|
"enabled": true, // Enable CDEK delivery?
|
|
"label": "CDEK" // Name of the CDEK delivery
|
|
}
|
|
},
|
|
"chats": [
|
|
{
|
|
"id": null, // Example: -1002599391893 (int) (negative number) The telegram chat identifier
|
|
"orders": true // Send orders? (for moderators)
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Suspensions
|
|
*System of suspensions of chat-robot and Web App*<br><br>
|
|
Make sure you have a **suspension** collection (can be created automatically)<br>
|
|
You can copy a clean suspension document without comments from here: `/examples/arangodb/collections/suspension.json`
|
|
```json
|
|
{
|
|
"end": 1726068961, // Unixtime
|
|
"targets": {
|
|
"chat-robot": true, // Block chat-robot
|
|
"web app": true // Block "Web App"
|
|
},
|
|
"access": {
|
|
"tester": true, // Account with `"tester": true`
|
|
"developer": true // Account with `"developer": true`
|
|
},
|
|
"description": {
|
|
"ru": "Разрабатываю каталог, поиск и корзину",
|
|
"en": "I am developing a catalog, search and cart"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Used by
|
|
*List of projects created on the basis of [huesos](https://git.svoboda.works/mirzaev/huesos)*
|
|
|
|
- ARMING [@arming_bot](https://t.me/arming_bot)<br>
|
|
*Russian weapons tuning shop* ([repository](https://git.svoboda.works/mirzaev/arming))
|
|
|
|
|
|
|
|
|