Commit f176256c authored by Денис Тормазов's avatar Денис Тормазов Committed by Maksim Baev

Удаление inc

parent 2558fc08
<?php
/**
* Slack API admin settings form
*/
function dru_slack_admin() {
$chanels = variable_get('slack_chanels');
$chanelsForms = [];
$i = 0;
if ($chanels) {
foreach ($chanels as $key => $val) {
$chanelsForms['inline'][] = _dru_slack_init_chanel($key, $val, $i);
$i++;
}
} else {
$chanelsForms['inline'][] = _dru_slack_init_chanel('', '', $i);
}
$chanelsForms['#prefix'] = '<div id="chanels"><h2>' . t('Slack chanels') . '</h2>';
$chanelsForms['#suffix'] = '</div>';
$form = [
'slack_team_hostname' => [
'#type' => 'textfield',
'#title' => t('Slack hostname'),
'#default_value' => variable_get('slack_team_hostname'),
'#description' => t('hostname without suffix ".slack.com"'),
'#required' => TRUE,
],
'slack_token' => [
'#type' => 'textfield',
'#title' => t('Auth token'),
'#default_value' => variable_get('slack_token'),
'#description' => t('You can create a token for your application on the next <a href="@url">page</a>', ['@url' => 'https://api.slack.com/custom-integrations/legacy-tokens']),
'#required' => TRUE,
],
'slack_approved_users' => [
'#type' => 'textfield',
'#title' => t('User list to access for slack commands'),
'#default_value' => variable_get('slack_approved_users'),
'#description' => t('Comma separated user list, who access to execute slack commands'),
'#required' => FALSE,
],
'container' => $chanelsForms,
'add_url' => [
'#type' => 'button',
'#value' => t('Add chanel'),
'#ajax' => [
'callback' => 'dru_slack_add_chanel',
'wrapper' => 'chanels',
'method' => 'replace',
'effect' => 'fade',
],
],
];
$settingsForm = system_settings_form($form);
$settingsForm['#submit'] = ['dru_slack_form_submit'];
return $settingsForm;
}
/**
* Формирует массив для инлайново формсета
*
* @param $label
* Название канала
* @param $value
* URL для сообщений в канал
* @param $i
* Порядковый номер для идентификации значений
*
* @return array
* Набор элементов для инлайн формы
*/
function _dru_slack_init_chanel($label, $value, $i) {
$output = [
'#prefix' => '<div style="display: flex;">',
'#suffix' => '</div>',
'label_' . $i => [
'#type' => 'textfield',
'#title' => t('Chanel'),
'#description' => t('Chanel name without #'),
'#attributes' => ['style' => 'margin-right: 2em'],
'#default_value' => $label,
'#required' => FALSE,
],
'value_' . $i => [
'#type' => 'textfield',
'#title' => t('Url'),
'#default_value' => $value,
'#required' => FALSE,
],
];
if ($label != '' && $value != '') {
$output['remove_' . $i] = [
'#type' => 'image_button',
'#src' => drupal_get_path('module', 'dru_slack') . '/img/garbage.svg',
'#attributes' => ['style' => 'height:1em; background: none; border: none; line-height:2; display: block; margin-top: 2em; margin-right: 0; fill: #0074BD'],
'#ajax' => [
'callback' => 'dru_slack_remove_chanel',
'wrapper' => 'chanels',
'method' => 'replace',
],
];
$output['send_message_' . $i] = [
'#type' => 'image_button',
'#src' => drupal_get_path('module', 'dru_slack') . '/img/sent-mail.svg',
'#attributes' => ['style' => 'height:1em; background: none; border: none; line-height:2; display: block; margin-top: 2em; margin-right: 0; fill: #0074BD'],
'#ajax' => [
'callback' => 'dru_slack_send_test_message',
],
];
}
return $output;
}
/**
* Возвращает подготовленный массив для сохранения в переменную каналов
*
* @param $values
* массив значений из $form_state
* @param int $trigger
* Указатель на удаляемый элемент
*
* @return array
*/
function _dru_slack_chanels_to_save($values, $trigger = -1) {
$data = [];
foreach ($values as $k => $v) {
if (substr($k, 0, 5) == 'label') {
$karr = explode('_', $k);
$i = end($karr);
if ($values[$k] != '' && $values["value_{$i}"] != '' && $trigger != $i) {
$data[$values[$k]] = $values["value_{$i}"];
}
}
}
return $data;
}
/**
* Добавление инлайновой формы в основную
*
* @param $form
* @param $form_state
*
* @return mixed
*/
function dru_slack_add_chanel($form, &$form_state) {
$form['container']['inline'][] = _dru_slack_init_chanel('', '', count($form['container']['inline']) - 2);
return $form['container'];
}
/**
* Удаление инлановой формы из основной
*
* @param $form
* @param $form_state
*
* @return mixed
*/
function dru_slack_remove_chanel($form, &$form_state) {
$tmp = explode('_', $form_state['triggering_element']['#name']);
$iter = end($tmp);
$inlinedata = _dru_slack_chanels_to_save($form_state['values'], $iter);
$old = variable_get('slack_chanels', []);
if ($old != $inlinedata) {
variable_set('slack_chanels', $inlinedata);
}
unset($form['container']['inline'][$iter]);
return $form['container'];
}
/**
* Отправка тестового сообщения в Slack
*
* @param $form
* @param $form_state
*
* @return null
*/
function dru_slack_send_test_message($form, &$form_state) {
$tmp = explode('_', $form_state['triggering_element']['#name']);
$iter = end($tmp);
$url = $form_state['values']['value_' . $iter];
$slack = new slackAPI();
$slack->notificate_by_url(
$url,
[
'text' => t('Test message'),
]
);
return NULL;
}
/**
* Slack API admin form submit
*
* @param $form
* @param $form_state
*/
function dru_slack_form_submit($form, &$form_state) {
$requiredKeys = [
'slack_token',
'slack_approved_users',
'slack_team_hostname',
];
foreach ($requiredKeys as $formKey) {
if ($form[$formKey]['#default_value'] != $form_state['values'][$formKey]) {
variable_set($formKey, $form_state['values'][$formKey]);
}
}
$inlinedata = _dru_slack_chanels_to_save($form_state['values']);
$old = variable_get('slack_chanels');
if ($old != $inlinedata) {
variable_set('slack_chanels', $inlinedata);
}
}
<?php
/**
* Implements hook_help().
*/
function dru_slack_help($path, $arg) {
$output = '';
if ($path == 'admin/help#dru_slack') {
$output .= '<h2>Первоначальная настройка</h2>';
$output .= '<ol>';
$output .= "<li><p>У Вас должен быть уже настроенный <b>Workspace</b> в Slack,
либо можете <a href='https://slack.com/create'>создать новый</a>.<br>
(<em>Для настройки модуля Вы должны обладать правами не ниже администратора.</em>)
</p></li>";
$output .= "<li><p>Далее необходимо <a href='https://api.slack.com/apps'>создать приложение</a></p></li>";
$output .= "<li><p>Для отправки инвайтов в Ваш workspace на электронный адрес
пользователей так же потребуется наличие токена.<br>
Сгенерировать новый токен для Вашего workspace можно на этой
<a href='https://api.slack.com/custom-integrations/legacy-tokens'>странице</a>
</p></li>";
$output .= "<li><p>Заполните поля <b>workspace</b> и <b>token</b>
соответствующими значениями на <a href='".url('admin/config/dru_slack/settings')."'>странице настроек модуля</a>
</p></li>";
$output .= '</ol>';
$output .= '<h2>Инвайты</h2>';
$output .= '<p>Для отправки инвайтов в Ваш workspace на электронный адрес
пользователей используется метод <b>invite($email)</b>
основного класса для работы с API Slack <b>slackAPI</b>.
Его можно вызвать в сабмите любой Вашей формы. Пример использования:
</p>';
$output .= '<pre>
require_once drupal_get_path("module", "dru_slack") . "/inc/slackAPI.php.inc";
function custom_form_submit($form, &$form_state) {
$email = $form_state["values"]["email"];
$slack = new slackAPI();
$result = $slack->invite($email);
drupal_set_message($result["message"], $result["status"]);
}
</pre>';
$output .= '<h2>Команды из Slack</h2>';
$output .= '<p>Для обработки команд из Slack существует динамический роут
<b>slack/callback/{method_name}</b>, где <em>method_name</em> -
название метода класса <b>slackAPI</b>.
</p>';
$output .= '<p>Команды могут использовать аргументы или обходиться без них.
Аргументы передаются через пробел в команде и обрабатываются на бекэнде, как обыкновенный массив.
Для создания своих методов для команд используйте примеры из класса <b>slackAPI</b>:
<em>call_without_args</em> и <em>call_with_args</em>.
</p>';
$output .= '<p>Свои команды Вы можете добавить в разделе <em>Slash commands</em>
на странице настроек <a href="https://api.slack.com/apps">вашего приложения</a>.
В <b>Request URL</b> нужно указать <em>{URL_сайта}/slack/callback/{название вашего метода для данной команды}</em>.
Остальное по желанию.
</p>';
$output .= "<p>Для предотвращения несанкционированного доступа к использованию команд лицами, не имеющими на то право,
на <a href='".url('admin/config/dru_slack/settings')."'>странице настроек модуля</a>
укажите через запятую ID участников Вашего workspace, которые будут иметь право на выполнение команд в соответствующем поле.
</p>";
$output .= '<h2>Сообщения в каналы Slack</h2>';
$output .= '<p>Модуль может слать сообщения в различные каналы Вашего workspace.
Эта возможность реализована двумя методами класса <b>slackAPI</b>:
</p>';
$output .= '<ul>';
$output .= '<li><b>notificate_by_chanel</b> - по названию канала</li>';
$output .= '<li><b>notificate_by_url</b> - по урлу</li>';
$output .= '</ul>';
$output .= '<p>Вторым аргументом методы принимают ассоциативный массив сообщения.
Подробнее о формате сообщений можно прочитать в
<a href="https://api.slack.com/docs/message-formatting">официальной документации</a>.
Пример использования:
</p>';
$output .= '<pre>
require_once drupal_get_path("module", "dru_slack") . "/inc/slackAPI.php.inc";
$slack = new slackAPI();
$ message = [
"attachments" => [
[
"title" => "Title",
"pretext" => "Pretext _supports_ mrkdwn",
"text" => "Testing *right now!*",
"mrkdwn_in" => ["text", "pretext"]
]
]
];
$slack->notificate_by_chanel("general", $message);
</pre>';
$output .= '<p>Интерфейс для управления доступными каналами для сообщений
Вы можете найти в разделе <em>Incoming Webhooks</em>
на странице настроек <a href="https://api.slack.com/apps">вашего приложения</a>.
Аналогично укажите на <a href='.url("admin/config/dru_slack/settings").'>странице настроек модуля</a>
маппинг <b>Канал->URL</b>(<em>Название канала будет использовано в качестве аргумента для <b>notificate_by_chanel()</b></em>).
</p>';
$output .= '<h2>Бейдж и информация об активности участников workspace</h2>';
$output .= '<p>Для показа бейджа, например на страницах GitHub используйте url
<b>{Ваш сайт}/slack/badge/{высота бейджа в px}/badge.svg</b>.
Информация об активности участников реализована методом класса <b>slackAPI</b>
<em>badge()</em>. Метод возвращает ассоциативный массив с ключами:
</p>';
$output .= '<ul>';
$output .= '<li><b>link</b> - ссылка на Ваш workspace</li>';
$output .= '<li><b>active</b> - количество активных участников</li>';
$output .= '<li><b>total</b> - всего участников</li>';
$output .= '</ul>';
}
return $output;
}
<?php
/**
* Created by PhpStorm.
* User: hulygun
* Date: 10.09.17
* Time: 23:11
*/
define('SLACK_INVITE_ALREADY_IN_TEAM', 'already_in_team');
define('SLACK_INVITE_SENT_RECENTLY', 'sent_recently');
define('SLACK_INVITE_ALREADY_INVITED', 'already_invited');
/**
* Class slackAPI
* Реализация интерфейса для работы с API Slack
*/
class slackAPI {
protected $hostname;
protected $token;
public function __construct() {
$this->hostname = variable_get('slack_team_hostname');
$this->token = variable_get('slack_token');
}
/**
* Отправка сообщений в Slack по урлу
*
* @param $url
* url, на который следует слать сообщение
* @param $message
* массив сообщения
*
* @return object
* drupal_http_request
*/
public function notificate_by_url($url, $message) {
$json_string = json_encode($message);
$options = [
'method' => 'POST',
'headers' => [
'Content-Type' => 'application/json',
'Content-Length' => strlen($json_string),
],
'data' => $json_string,
];
return drupal_http_request($url, $options);
}
/**
* Отправка сообщений в Slack по названию канала
*
* @param $chanel
* название канала
* @param $message
* массив сообщения
*
* @return object
*/
public function notificate_by_chanel($chanel, $message) {
$chanels = variable_get('slack_chanels');
if (is_array($chanels) && isset($chanels[$chanel])) {
return $this->notificate_by_url($chanels[$chanel], $message);
} else {
watchdog('dru_slack', 'Unknown chanel name as @chanel', ['@chanel' => $chanel]);
}
}
/**
* Отправка инвайтов в Slack по email
*
* @param $email
* email получателя
*
* @return array
*/
public function invite($email) {
$url = "https://{$this->hostname}.slack.com/api/users.admin.invite?t=" . time();
$data = [
'_attempts' => 1,
'email' => $email,
'set_active' => 'true',
'token' => $this->token,
];
$data = drupal_http_build_query($data);
$options = [
'method' => 'POST',
'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
'data' => $data,
];
$response = drupal_http_request("{$url}", $options);
$status = 'error';
if ($response->code == 200) {
$data = drupal_json_decode($response->data);
if (!empty($data['ok'])) {
$message = t('The invite sent to email @email', ['@email' => $email]);
$status = 'status';
}
else {
$status = 'warning';
switch ($data['error']) {
case SLACK_INVITE_ALREADY_IN_TEAM:
$message = t('User with email @email already in https://@hostname.slack.com/', ['@email' => $email, '@hostname' => $this->hostname]);
break;
case SLACK_INVITE_SENT_RECENTLY:
$message = t('The invite sent recently to email @email', ['@email' => $email]);
break;
case SLACK_INVITE_ALREADY_INVITED:
$message = t('User with email @email already invited', ['@email' => $email]);
break;
default:
$message = $data['error'];
$status = 'error';
break;
}
}
}
else {
$message = t('There was an error sending your invite. Please contact the administrator for more details.');
}
return ['status' => $status, 'message' => $message];
}
/**
* Получение данных об участниках Slack team
*
* @return array
*/
public function badge() {
$url = "https://slack.com/api/users.list";
$data = [
'token' => $this->token,
'presence' => true,
];
$data = drupal_http_build_query($data);
$response = drupal_http_request($url.'?'.$data);
$active = 0;
$total = 0;
if ($response->code == 200) {
$data = drupal_json_decode($response->data);
if (isset($data['members'])) {
$total = count($data['members']);
$active = count(array_filter($data['members'], function ($user) {
return (isset($user['presence']) && $user['presence'] == 'active');
}));
}
}
return [
'link' => "https://{$this->hostname}.slack.com",
'active' => $active,
'total' => $total,
];
}
/**
* Метод, который вызывает остальные по строковому значению.
* Через него все кастомные команды
*
* @param $action
* Название метода
* @param $args
* Массив аргументов для выполнения команды
*
* @return array
* Ответ для передачи сообщения в Slack
*/
public function run($action, $args) {
if (is_callable([$this, $action])) {
return $this->$action($args);
}
else {
return [
"attachments" => [
[
"color" => "#ff9933",
"text" => t(":radioactive_sign: Unknown command *@action*", ['@action' => $action]),
],
],
];
}
}
/**
* Примеры для создания своих команд для бота с аргументами и без
*
* public function call_without_args($args) {
* return ['text' => t("This message return after call the method **call_without_args**")];
* }
*
* public function call_with_args($args) {
* return ['text' => t("This message return after call the method **call_with_args** с аргументами {implode(', ', $args)}")];
* }
*/
public function invite_user($args) {
$args_len = count($args);
$message = [
"attachments" => []
];
if ($args_len == 0) {
$message['attachments'][0]['pretext'] = 'Введите email';
} elseif ($args_len == 1) {
$invite = $this->invite($args[0]);
switch ($invite['status']) {
case 'warning':
$color = '#ff7909';
break;
case 'error':
$color = '#f00';
break;
default:
$color = '#390';
break;
}
$message['attachments'][0]['pretext'] = 'Отправка приглашения выполнена';
$message['attachments'][0]['color'] = $color;
$message['attachments'][0]['text'] = $invite['message'];
} else {
$message['attachments'][0]['pretext'] = 'Слишком много аргументов';
}
return $message;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment