Telegram chat widget self-hosted Debian Linux + Intergram GitHub skript + Node.js

Existuje řada komunikačních platforem s možností integrace do webových stránek. Několik z nich je vyloženě povedených, masivně využívaných a progresivních i v tom dobrém slova smyslu. Snad pouze jediná platforma je i oblíbená, i masivně používaná i progresivní ve smyslu původního plánu. To jest v rovině komunikace a uživatelské přívětivosti. Telegram (TG). Jedna z mála služeb kde nikoho nezajímá kolik vám je let, kolik vážite ani dalších asi tisíc věcí.

Na druhou stranu na to jak jednoduchá, bezpečná a GDPR friendly komunikační platforma Telegram je.. přituhuje na straně implementace. Pokud třeba provozujete e-shop s podporou přihlášení pomocí sociálních sítí či dalších služeb (toto API umí a poskytuje třeba GitHub, Facebook, Twitter, Google, Telegramu a další) víte, že existue několik pluginů, žádný ale neumí vše a už vůbec žádný zákazníckou podporu pomocí Telegram chatu.

Až na jednu výjimku na kterou nepotřebujete 2500 Kč za plugin a další desítku za implementaci. Idoco, webový Telegram chat widget, ze kterého příjde zpráva přímo na váš mobil. Nainstalujeme a vyzkoušíme :)

Intergram Telegram skript

cd /tam/kam/chcete/umístit (stáhne se jako intergram)
git clone https://github.com/idoco/intergram.git
cd intergram/

Instalace (aktuálního) Node.js

Pokud Node.js používáte (třeba na pohon vizuálního editoru v mediawiki) můžete přeskočit na pm2 nebo úpravu níž.. Nainstalujeme novější Node.js

curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
apt install -y nodejs

Kontrola verze node.js a správce ballíčku pro node.js – npm

npm -v
nodejs -v

Ve složce kde je stažený / naklonovaný Intergram chat z GitHub je soubor package.json (obsahuje všechny potřebné informace a seznam závislostí) spustíme instalaci aplikace ve složce intergram

npm install

V terminálu je první hláška (bude se ještě opakovat) o možnosti upgrade na novější verzi. Dle instrukce v terminálu provedeme upgrade npm

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: intergram@0.0.1
npm ERR! Found: webpack@1.15.0
npm ERR! node_modules/webpack
npm ERR!   webpack@"^1.14.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer webpack@"^4.0.0 || ^5.0.0" from webpack-dev-server@3.11.3
npm ERR! node_modules/webpack-dev-server
npm ERR!   dev webpack-dev-server@"^3.1.11" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See /root/.npm/eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2022-02-09T11_25_10_394Z-debug-0.log
npm install -g npm@8.4.1

provedeme i v terminálu doporučený audit příkazem

npm audit fix

Pokusíme se o další instalaci a znovu spustíme

npm install

Další hláška.. Jsou vyžadované neaktuální verze balíčků, ten nejpodstatnější webpack je v únoru 2022 aktuálně o nějaký ten rok a půl mladší :o) Použijeme medicínu (funguje rovněž i pro npm uninstall)

npm install --legacy-peer-deps

Po tom co doběhne instalace pro jistotu i

npm audit fix --force
npm fund

npm install po uninstall

npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'intergram@0.0.1',
npm WARN EBADENGINE   required: { node: '6.9.1', npm: '3.10.8' },
npm WARN EBADENGINE   current: { node: 'v16.13.2', npm: '8.4.1' }
npm WARN EBADENGINE }

> intergram@0.0.1 postinstall
> npm run build


> intergram@0.0.1 build
> shx mkdir -p dist && shx cp *.html dist && shx cp -r ./media dist && shx cp -r ./css dist && webpack -p

CLI for webpack must be installed.
  webpack-cli (https://github.com/webpack/webpack-cli)

We will use "npm" to install the CLI via "npm install -D webpack-cli".
Do you want to install 'webpack-cli' (yes/no):

yes + Enter

Installing 'webpack-cli' (running 'npm install -D webpack-cli')...
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'intergram@0.0.1',
npm WARN EBADENGINE   required: { node: '6.9.1', npm: '3.10.8' },
npm WARN EBADENGINE   current: { node: 'v16.13.2', npm: '8.4.1' }
npm WARN EBADENGINE }

added 27 packages, and audited 625 packages in 5s

57 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
[webpack-cli] Error: Unknown option '-p'
[webpack-cli] Run 'webpack --help' to see available commands and options
npm ERR! code 2
npm ERR! path /opt/intergram
npm ERR! command failed
npm ERR! command sh -c npm run build

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2022-02-09T11_31_18_805Z-debug-0.log

Znovu :)

npm install --legacy-peer-deps

chyba.. upravime package.json v části node server.js / webpack na

  "scripts": {
    "start": "node server.js",
    "postinstall": "npm run build",
    "dev": "start  http://localhost:3000/demo.html & node devServer.js",
    "build": "shx mkdir -p dist && shx cp *.html dist && shx cp -r ./media dist && shx cp -r ./css dist && webpack --mode production",
    "test": "npm run -s lint",
    "lint": "eslint src"

Pro jistotu si poznačíme proměnnou && webpack –mode production –env production .. následuje další chyba webpack

[webpack-cli] Failed to load '/opt/intergram/webpack.config.js' configsabled.
[webpack-cli] TypeError: webpack.optimize.UglifyJsPlugin is not a constructor
    at Object.<anonymous> (/opt/intergram/webpack.config.js:31:9)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at WebpackCLI.tryRequireThenImport (/opt/intergram/node_modules/webpack-cli/lib/webpack-cli.js:244:16)
    at loadConfigByPath (/opt/intergram/node_modules/webpack-cli/lib/webpack-cli.js:1712:30)
    at WebpackCLI.loadConfig (/opt/intergram/node_modules/webpack-cli/lib/webpack-cli.js:1832:36)

upravíme sobor webpack.config.json a umažeme

        new webpack.optimize.UglifyJsPlugin({
            compressor: {
                warnings: false
            }
        })
    ]
};

a nahradíme s

const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
  // ...
  optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
  },
  // ...
};

znovu :)

nmp install --legacy-peer-deps
[webpack-cli] Failed to load '/opt/intergram/webpack.config.js' config
[webpack-cli] /opt/intergram/webpack.config.js:31
const TerserPlugin = require("terser-webpack-plugin");
^^^^^

SyntaxError: Unexpected token 'const'
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at WebpackCLI.tryRequireThenImport (/opt/intergram/node_modules/webpack-cli/lib/webpack-cli.js:244:16)
    at loadConfigByPath (/opt/intergram/node_modules/webpack-cli/lib/webpack-cli.js:1712:30)
npm ERR! code 2
npm ERR! path /opt/intergram
npm ERR! command failed
npm ERR! command sh -c npm run build

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2022-02-09T11_57_12_037Z-debug-0.log

Nemáme zapsanou závislost v config.json terser-webpack-plugin nainstalujeme

npm install terser
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'intergram@0.0.1',
npm WARN EBADENGINE   required: { node: '6.9.1', npm: '3.10.8' },
npm WARN EBADENGINE   current: { node: 'v16.13.2', npm: '8.4.1' }
npm WARN EBADENGINE }

added 5 packages, removed 5 packages, changed 1 package, and audited 625 packages in 3s

57 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Hotovo. Najhorší máme za sebou. Můžeme spustit demo které je součástí staženého Idoco Intergram skriptu pomocí příkazu (stále jsme ve složce intergram chatu) node server.js demo chat odpoví na jednu správu, víc od něj nečekejte. Pokračujeme na obligátní Telegram proceduru. Pokud používáte TG zajisté máte Bota a k dispozici token Bota, což je x místní řetězec který vám @BotFather sdělí po registraci vlastního Bota v okně chatu. Registrace Telegram bota je široce popsaní i fotografovaná procedura, přeskočíme k instalaci pm2.

Instalace pm2

Tento balíček z npm úložiště umožní spustit náš nodej.js server na pozadí a ukončit terminál. V opačném případě by po ukončení termínalu, kde byl spuštěn node.js server skončil i tento.

npm install pm2 -g

Provedeme i v terminálu doporučenou operaci fund (a čteme)

npm fund

Úprava konfigurace pro Node.js server

V kódu vyhledáme frázi TELEGRAM_TOKEN která je zmňovaná v manuálu (zdroj na konci článku) v souvislosti se zadáním Telegram Bot tokenu, který máme připravený

grep 'TELEGRAM_TOKEN' * -d recurse -l

Jediný soubor který toto pole obsahuje je server.js

nano server.js

Část kódu která kde se nahradí TELEGRAM_TOKEN skutečným tokenem který nám poskytl @BotFather

function sendTelegramMessage(chatId, text, parseMode) {
    request
        .post('https://api.telegram.org/bot' + process.2987931029:BFON2AYUCi2CQo1A2tkLDB7iSBX8YZplRWp + '/sendMessage')
        .form({
            "chat_id": chatId,
            "text": text,
            "parse_mode": parseMode
        });
}

Dle vlastních potřeb, uživatele pod kterým chceme aby server běžel a místa, kde server hostujeme, upravíme oprávnění složky a skriptů an požadovaného vlastníka. V našem příkladu je použitý uživatel aladin který je v skupině www-data

cd ..
chown -R aladin:www-data intergram/

Pod stejným uživatelem ladin spustíme node.js server Intergram, s instanci pojmenovanou jako telegramsrv a parametrem –watch

cd intergram/
sudo -u aladin pm2 start server.js --name "telegramsrv" --watch

Sever je spuštěn a v terminálu barevná tabulka se statistikou paměti, zátěže CPU atd..

NPM Node.js server databáza
NPM Node server Telegram DB

Pro případ restartu (hardware) serveru, instanci zapíšeme pro automatický (re)start pomocí

pm2 startup
pm2 save

Odbočka: šifrování SSL a certifikáty

Pokud server i widget pro chat provozujete na jednom místě, asi nebude potřeba hrotit SSL, pokud ale myslíte, že šifrování potřebujete lze použít třeba pro nginx nebo apache2 již vygenerované certifikáty a vyrobit z nich .pem, kterým můžete později nakrmit server.js skript. Srozumitelně popsáno kupříkladu v článku How to use TLS/SSL with Node.js na sitepoint.

cd /kde/jsou /ssl/certifikáty
cat mojedomena.cz-le.{key,crt} > telegram.pem

V kódu serveru příprava na SSL není, to znamená, že je potřeba pář řádku kódu dopsat, nebo použít webpack.

Ověření serveru zavoláme GET hook na Telegram server

Potřebujeme znovu použít token svého Telegram bota, ano toho samého kterého token již je uložený v souboru server.js. Tento spolu s URL serveru kde bude běžet Telegram server, vložíme do URL a odešleme v prohlížeči – jako standardní dotaz na otevření webové stránky. Nebo pomocí curl GET v terminálu. Zde zavolání pomocí prohlížeče:

https://api.telegram.org/bot2987931029:BFON2AYUCi2CQo1A2tkLDB7iSBX8YZplRWp/setWebhook?url=https://mojewebovka.cz/hook

Odezva ze serveru v prohlížeči je hláška (ideálně) Webhook was set

Telegram Node.js json web token
Telegram Web token ID

TG chat widget – chat ID

K poslednímu kroku jsou potřeba dvě věci. Znát cetu /intergram/dist/js/widget.js k widgetu ve složce intergram a vlastní Telegram chat ID, kam chcete aby vám lidé z webu psali. Telgram chat ID zjistíte jednoduše (třeba na telefonu) vyhledáním @RawDataBot a enter načež uvidíte svoje Telegram ID, to jest chatu kam vám budou chodit zprávy z webové stránky, kde je umístěný widget

FatherBot Telegram Token
FatherBot

Telegram chat widget skript pro umístění do webové stránky

Před umístěním kódu widgetu na web nastavíme poslední tři položky. Vlastní Telegram chat ID uživatele kterému budou chodit zprávy z web chat widgetu, instanci Telegram serveru (window.intergramServer) pouze pokud je na jiném místě než widget – pokud je na stejném serveru nevyplňovat! A cestu k souboru widget.js ve složce intergram. Upravený skript widgetu vypadá:

<script> 
    window.intergramId = "932853543"
    window.intergramServer = ""
</script>
<script id="intergram" type="text/javascript" src="/intergram/dist/js/widget.js"></script>

Otevřeme webovou stránku do které jsme vložili kód.. Pro náš účel jsem použili testovací instalaci Wordpres + Telegram se šablonou GeneratePress, kde jsem kód vložili do pomocí konfigurace Wordpress / Widget / Spodní pruh. To znamená, že kód se zobrazí na každé stránce zveřejnené na blogu. Kód lze samozřejmě pomocí (kupříkladu) GeneratePress Elementu zobrazovat pouze na vybraných místech webu.

Telegram web chat widget
Webový Widget

Telegram chat Widget je základním nastavení modrý, v angličtině s předpřipravenou hláškou Hello! How can we help you? .. Vyhledáním této fráze (třeba) pomocí příkazu grep lze snadno najít cestu, kde lze nakonfigurovat hlášky, barev a další nastavení, které tento Telegram widget podporuje.

Užitečné

Zvuk v Telegram chat Windows 10 / 11.
Manuál a stránka vývojáře Intergram.

ICTIS.CZ