Skip to content

Commit fb20a8f

Browse files
committed
Initial version of the PHP Telegram Bot role for Ansible.
1 parent f10fcfa commit fb20a8f

14 files changed

+501
-2
lines changed

README.md

+126-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,126 @@
1-
# ansible-role-php-telegram-bot
2-
Ansible role to set up PHP Telegram Bots.
1+
# Ansible Role for PHP Telegram Bot
2+
3+
<!-- [![Build Status][1]][2] -->
4+
5+
**This project is still a work in progress, use at your own risk! For now, you will most probably have to explore the code to understand what this role does exactly.**
6+
7+
Installs and configures [PHP Telegram Bots][php-telegram-bot] on Debian/Ubuntu servers.
8+
This role uses the [PHP Telegram Bot Manager][php-telegram-bot-manager] project and makes use of [`vlucas/phpdotenv`][phpdotenv] for all configurable values.
9+
10+
**Note:** This role does not install any web or database server!
11+
It assumes that you have a functioning web server with PHP and composer installed.
12+
13+
There are two different ways this role will work for you:
14+
**A basic default bot**
15+
This method installs a very basic bot into your defined working directory.
16+
All parameters are passed directly using the `php_telegram_bot_bots` array.
17+
18+
**An existing project that exists in a git repository**
19+
When you already have an existng project that makes use of the [PHP Telegram Bot Manager][php-telegram-bot-manager], you can simply define the path to your git repository using the `project_repo` (and `project_repo_branch`) parameters in the `php_telegram_bot_bots` array.
20+
21+
## Requirements
22+
23+
- git (can be installed using the [`geerlingguy.git`][geerlingguy.git] role)
24+
- Composer (can be installed using the [`geerlingguy.composer`][geerlingguy.composer] role)
25+
26+
**Webserver**
27+
You can use whatever you want. You just need to create a site/vhost that points to the correct root of the Telegram Bot directories.
28+
I recommend using Nginx, which can be installed easily with the [`geerlingguy.nginx`][geerlingguy.nginx] role.
29+
30+
**Database**
31+
To use the database for your bot(s), make sure you have a functioning connection to the database server.
32+
If it's on the same machine, you can use the the [`geerlingguy.mysql`][geerlingguy.mysql] role.
33+
For any external server, you just need to be able to access the database with your credentials.
34+
35+
## Role Variables
36+
37+
```
38+
php_telegram_bot_composer_package: noplanman/telegram-bot-manager
39+
php_telegram_bot_composer_version: ''
40+
php_telegram_bot_mysql_structure: vendor/longman/telegram-bot/structure.sql
41+
42+
php_telegram_bot_websrv_user: www-data
43+
php_telegram_bot_websrv_group: www-data
44+
45+
php_telegram_bot_bots: []
46+
47+
# php_telegram_bot_bots:
48+
# # Simple bot (minimal)
49+
# - api_key: 12345:api_key
50+
# working_dir: /var/www/simplebot_minimal
51+
#
52+
# # Simple bot (with db)
53+
# - api_key: 12345:api_key
54+
# bot_username: my_bot
55+
# working_dir: /var/www/simplebot_with_db
56+
# mysql:
57+
# host: localhost
58+
# user: root
59+
# password: root
60+
# database: db
61+
#
62+
# # Simple bot (with webhook)
63+
# - api_key: 12345:api_key
64+
# bot_username: my_bot
65+
# working_dir: /var/www/simplebot_with_webhook
66+
# secret: super-secret
67+
# webhook:
68+
# url: my.webhook.url
69+
#
70+
# # Project bot (with webhook)
71+
# - api_key: 12345:api_key
72+
# bot_username: my_bot
73+
# project_repo: https://projectrepo.git
74+
# project_dotenv: prod.env.j2
75+
# working_dir: /var/www/projectbot
76+
# secret: super-secret
77+
# webhook:
78+
# url: project.webhook.url
79+
# mysql:
80+
# host: db.server
81+
# user: root
82+
# password: root
83+
# database: db
84+
# structure: my-custom-db-structure.sql
85+
```
86+
87+
Available fields for `php_telegram_bot_bots` entry are the ones available for the [PHP Telegram Bot Manager][php-telegram-bot-manager]. Simply use YAML format to define variables in the same structure as the [`manager.php`][manager.php-example] parameters array.
88+
89+
## Role Tags
90+
91+
Each part of the setup has a tag.
92+
93+
```
94+
php_telegram_bot:install # Installation of all bots.
95+
php_telegram_bot:database # Set up the databases.
96+
php_telegram_bot:webhook # Set the webhooks.
97+
```
98+
99+
## Dependencies
100+
101+
None.
102+
103+
## Example Playbook
104+
105+
```
106+
---
107+
- hosts: www-server
108+
become: yes
109+
roles:
110+
- php-telegram-bot.php-telegram-bot
111+
```
112+
113+
## License
114+
115+
MIT
116+
117+
[1]: https://travis-ci.org/php-telegram-bot/ansible-role-php-telegram-bot.svg?branch=master "Travis-CI Build Status"
118+
[2]: https://travis-ci.org/php-telegram-bot/ansible-role-php-telegram-bot "Travis-CI Tests"
119+
[php-telegram-bot]: https://github.com/php-telegram-bot/ "PHP Telegram Bot"
120+
[php-telegram-bot-manager]: https://github.com/php-telegram-bot/telegram-bot-manager "PHP Telegram Bot Manager"
121+
[manager.php-example]: https://github.com/php-telegram-bot/example-bot/blob/master/manager.php "manager.php example"
122+
[phpdotenv]: https://github.com/vlucas/phpdotenv/ "phpdotenv"
123+
[geerlingguy.git]: https://github.com/geerlingguy/ansible-role-git "Git Ansible role"
124+
[geerlingguy.composer]: https://github.com/geerlingguy/ansible-role-composer "Composer Ansible role"
125+
[geerlingguy.nginx]: https://github.com/geerlingguy/ansible-role-nginx "Nginx Ansible role"
126+
[geerlingguy.mysql]: https://github.com/geerlingguy/ansible-role-mysql "MySQL Ansible role"

Vagrantfile

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
role = File.basename(File.expand_path(File.dirname(__FILE__)))
2+
3+
boxes = [
4+
{
5+
:name => "ubuntu-1204",
6+
:box => "opscode-ubuntu-12.04",
7+
:url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-12.04_chef-provisionerless.box",
8+
},
9+
{
10+
:name => "ubuntu-1404",
11+
:box => "opscode-ubuntu-14.04",
12+
:url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-14.04_chef-provisionerless.box",
13+
},
14+
{
15+
:name => "ubuntu-1604",
16+
:box => "opscode-ubuntu-16.04",
17+
:url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_ubuntu-16.04_chef-provisionerless.box",
18+
},
19+
{
20+
:name => "debian-711",
21+
:box => "opscode-debian-7.11",
22+
:url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.11_chef-provisionerless.box",
23+
},
24+
{
25+
:name => "debian-85",
26+
:box => "opscode-debian-8.5",
27+
:url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-8.5_chef-provisionerless.box",
28+
},
29+
]
30+
31+
Vagrant.configure("2") do |config|
32+
boxes.each do |box|
33+
config.vm.define box[:name] do |vms|
34+
vms.vm.box = box[:box]
35+
vms.vm.box_url = box[:url]
36+
vms.vm.hostname = "ansible-#{role}-#{box[:name]}"
37+
38+
vms.vm.provider "virtualbox" do |v|
39+
v.customize ["modifyvm", :id, "--cpuexecutioncap", "50"]
40+
v.customize ["modifyvm", :id, "--memory", "256"]
41+
end
42+
43+
vms.vm.provision :ansible do |ansible|
44+
ansible.playbook = "tests/vagrant.yml"
45+
ansible.verbose = "vv"
46+
end
47+
end
48+
end
49+
end

defaults/main.yml

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
php_telegram_bot_composer_package: noplanman/telegram-bot-manager
3+
php_telegram_bot_composer_version: ''
4+
php_telegram_bot_mysql_structure: vendor/longman/telegram-bot/structure.sql
5+
6+
php_telegram_bot_websrv_user: www-data
7+
php_telegram_bot_websrv_group: www-data
8+
9+
php_telegram_bot_bots: []
10+
# php_telegram_bot_bots:
11+
# # Simple bot (minimal)
12+
# - api_key: 12345:api_key
13+
# working_dir: /var/www/simplebot_minimal
14+
#
15+
# # Simple bot (with db)
16+
# - api_key: 12345:api_key
17+
# bot_username: my_bot
18+
# working_dir: /var/www/simplebot_with_db
19+
# mysql:
20+
# host: localhost
21+
# user: root
22+
# password: root
23+
# database: db
24+
#
25+
# # Simple bot (with webhook)
26+
# - api_key: 12345:api_key
27+
# bot_username: my_bot
28+
# working_dir: /var/www/simplebot_with_webhook
29+
# secret: super-secret
30+
# webhook:
31+
# url: my.webhook.url
32+
#
33+
# # Project bot
34+
# - api_key: 12345:api_key
35+
# bot_username: my_bot
36+
# project_repo: https://projectrepo.git
37+
# working_dir: /var/www/projectbot
38+
# mysql:
39+
# host: db.server
40+
# user: root
41+
# password: root
42+
# database: db
43+
# structure: my-custom-db-structure.sql

files/create_db_structure.php

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
/**
3+
* Connect to a MySQL server and execute all queries in the passed file.
4+
* note: This script has no error handling, make sure the parameters are complete.
5+
*
6+
* Example call:
7+
* $ php create_db_structure.php \
8+
* host='localhost' \
9+
* user='root' \
10+
* password='root' \
11+
* database='my_db' \
12+
* encoding='utf8mb4' \
13+
* file='/path/to/queries.sql'
14+
*/
15+
16+
(isset($argc) && $argc > 1) || exit(1);
17+
18+
// We don't need the first arg, which is the filename.
19+
$args = array_slice($argv, 1);
20+
$vars = [];
21+
22+
foreach ($args as $arg) {
23+
@list($key, $val) = explode('=', $arg);
24+
isset($key, $val) && $vars[$key] = $val;
25+
}
26+
27+
try {
28+
$dsn = 'mysql:host=' . $vars['host'] . ';dbname=' . $vars['database'];
29+
$options = [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . $vars['encoding']];
30+
31+
$pdo = new PDO($dsn, $vars['user'], $vars['password'], $options);
32+
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
33+
34+
$tables_before = $pdo->query('SHOW tables')->fetchAll();
35+
36+
$pdo->beginTransaction();
37+
$pdo->exec('SET FOREIGN_KEY_CHECKS = 0;');
38+
$queries = explode(';', file_get_contents($vars['file']));
39+
$changes = 0;
40+
foreach ($queries as $query) {
41+
trim($query) && $pdo->exec($query);
42+
}
43+
$pdo->exec('SET FOREIGN_KEY_CHECKS = 1;');
44+
$pdo->commit();
45+
46+
$tables_after = $pdo->query('SHOW tables')->fetchAll();
47+
48+
echo $tables_before !== $tables_after ? 'Tables updated' : 'No changes';
49+
exit(0);
50+
} catch (Exception $e) {
51+
exit(1);
52+
} catch (Throwable $e) {
53+
exit(1);
54+
}

files/manager.default.php

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
use Dotenv\Dotenv;
4+
use Longman\TelegramBot\Exception;
5+
use Longman\TelegramBot\TelegramLog;
6+
use NPM\TelegramBotManager\BotManager;
7+
8+
// Composer autoloader.
9+
require_once __DIR__ . '/../vendor/autoload.php';
10+
(new Dotenv(__DIR__ . '/..'))->load();
11+
12+
$debug = (bool) getenv('TG_DEBUG');
13+
14+
try {
15+
// Vitals!
16+
$params = [
17+
'api_key' => getenv('TG_API_KEY'),
18+
];
19+
foreach (['bot_username', 'secret'] as $extra) {
20+
if ($param = getenv('TG_' . strtoupper($extra))) {
21+
$params[$extra] = $param;
22+
}
23+
}
24+
25+
// Database connection.
26+
if (getenv('TG_DB_HOST')) {
27+
$params['mysql'] = [
28+
'host' => getenv('TG_DB_HOST'),
29+
'user' => getenv('TG_DB_USER'),
30+
'password' => getenv('TG_DB_PASSWORD'),
31+
'database' => getenv('TG_DB_DATABASE'),
32+
];
33+
}
34+
35+
// Optional extras.
36+
$extras = ['admins', 'botan', 'commands', 'cron', 'limiter', 'logging', 'paths', 'valid_ips', 'webhook'];
37+
foreach ($extras as $extra) {
38+
if ($param = getenv('TG_' . strtoupper($extra))) {
39+
$params[$extra] = json_decode($param, true);
40+
}
41+
}
42+
43+
$bot = new BotManager($params);
44+
$bot->run();
45+
} catch (Exception\TelegramException $e) {
46+
TelegramLog::error($e);
47+
$debug && print $e->getMessage() . PHP_EOL;
48+
} catch (\Exception $e) {
49+
TelegramLog::error($e);
50+
$debug && print $e->getMessage() . PHP_EOL;
51+
} catch (\Throwable $e) {
52+
TelegramLog::error($e);
53+
$debug && print $e->getMessage() . PHP_EOL;
54+
}

meta/main.yml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
galaxy_info:
3+
author: Armando Lüscher
4+
description: Install and run PHP Telegram Bots.
5+
license: MIT
6+
min_ansible_version: 2.0.0.0
7+
platforms:
8+
- name: Ubuntu
9+
versions:
10+
- precise
11+
- trusty
12+
- xenial
13+
- name: Debian
14+
versions:
15+
- wheezy
16+
- jessie
17+
galaxy_tags:
18+
- php
19+
- telegram
20+
- bot
21+
- webhook
22+
dependencies: []

tasks/database.yml

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
3+
- block:
4+
- name: Create temporary file for database structure creation script.
5+
tempfile:
6+
register: php_telegram_bot_tmp_mysql_structure_file
7+
changed_when: no
8+
9+
- name: Ensure database structure creation script is created.
10+
copy:
11+
src: create_db_structure.php
12+
dest: "{{ php_telegram_bot_tmp_mysql_structure_file.path }}"
13+
changed_when: no
14+
15+
- name: Ensure database structure is present on first install.
16+
shell: >
17+
php '{{ php_telegram_bot_tmp_mysql_structure_file.path }}'
18+
host='{{ item.item.mysql.host }}'
19+
user='{{ item.item.mysql.user }}'
20+
password='{{ item.item.mysql.password }}'
21+
database='{{ item.item.mysql.database }}'
22+
encoding='{{ item.item.mysql.encoding | default('utf8mb4') }}'
23+
file='{{ item.item.mysql.structure | default(item.item.working_dir + '/' + php_telegram_bot_mysql_structure) }}'
24+
with_items: "{{ php_telegram_bot_bots_installed.results }}"
25+
when: item.changed and item.item.mysql is defined
26+
register: php_telegram_bot_mysql_structure_set_up
27+
changed_when: php_telegram_bot_mysql_structure_set_up.stdout != 'No changes'
28+
29+
- name: Remove temporary database structure creation script.
30+
file:
31+
path: "{{ php_telegram_bot_tmp_mysql_structure_file.path }}"
32+
state: absent
33+
changed_when: no
34+
35+
when: php_telegram_bot_bots_installed.changed
36+
no_log: yes

0 commit comments

Comments
 (0)