Initial Upload
This commit is contained in:
commit
793420684e
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*.zip
|
33
.travis.yml
Normal file
33
.travis.yml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
language: php
|
||||||
|
sudo: false
|
||||||
|
notifications:
|
||||||
|
email: false
|
||||||
|
|
||||||
|
php:
|
||||||
|
- 7.0
|
||||||
|
- 5.6
|
||||||
|
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- PLUGIN=Slack
|
||||||
|
- KANBOARD_REPO=https://github.com/kanboard/kanboard.git
|
||||||
|
matrix:
|
||||||
|
- DB=sqlite
|
||||||
|
- DB=mysql
|
||||||
|
- DB=postgres
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
|
||||||
|
install:
|
||||||
|
- git clone --depth 1 $KANBOARD_REPO
|
||||||
|
- ln -s $TRAVIS_BUILD_DIR kanboard/plugins/$PLUGIN
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- cd kanboard
|
||||||
|
- phpenv config-add tests/php.ini
|
||||||
|
- composer install
|
||||||
|
- ls -la plugins/
|
||||||
|
|
||||||
|
script:
|
||||||
|
- phpunit -c tests/units.$DB.xml plugins/$PLUGIN/Test/
|
22
LICENSE
Normal file
22
LICENSE
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Original work Copyright (c) 2014-2016 Frédéric Guillot
|
||||||
|
Modified work Copyright (c) 2019 Ryonez Coruscare
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
6
Locale/cs_CZ/translations.php
Normal file
6
Locale/cs_CZ/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/da_DK/translations.php
Normal file
6
Locale/da_DK/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/de_DE/translations.php
Normal file
6
Locale/de_DE/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/es_ES/translations.php
Normal file
6
Locale/es_ES/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/fi_FI/translations.php
Normal file
6
Locale/fi_FI/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/fr_FR/translations.php
Normal file
6
Locale/fr_FR/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/hu_HU/translations.php
Normal file
6
Locale/hu_HU/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/id_ID/translations.php
Normal file
6
Locale/id_ID/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/it_IT/translations.php
Normal file
6
Locale/it_IT/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/ja_JP/translations.php
Normal file
6
Locale/ja_JP/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/nb_NO/translations.php
Normal file
6
Locale/nb_NO/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/nl_NL/translations.php
Normal file
6
Locale/nl_NL/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/pl_PL/translations.php
Normal file
6
Locale/pl_PL/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/pt_BR/translations.php
Normal file
6
Locale/pt_BR/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/pt_PT/translations.php
Normal file
6
Locale/pt_PT/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/ru_RU/translations.php
Normal file
6
Locale/ru_RU/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/sr_Latn_RS/translations.php
Normal file
6
Locale/sr_Latn_RS/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/sv_SE/translations.php
Normal file
6
Locale/sv_SE/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/th_TH/translations.php
Normal file
6
Locale/th_TH/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/tr_TR/translations.php
Normal file
6
Locale/tr_TR/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
6
Locale/zh_CN/translations.php
Normal file
6
Locale/zh_CN/translations.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
// 'Help on Discord integration' => '',
|
||||||
|
);
|
||||||
|
|
5
Makefile
Normal file
5
Makefile
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
plugin=Slack
|
||||||
|
|
||||||
|
all:
|
||||||
|
@ echo "Build archive for plugin ${plugin} version=${version}"
|
||||||
|
@ git archive HEAD --prefix=${plugin}/ --format=zip -o ${plugin}-${version}.zip
|
182
Notification/Discord.php
Normal file
182
Notification/Discord.php
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Plugin\Discord\Notification;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
use Kanboard\Core\Notification\NotificationInterface;
|
||||||
|
use Kanboard\Model\TaskModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discord Notification
|
||||||
|
*
|
||||||
|
* @package notification
|
||||||
|
* @author Ryonez Coruscare
|
||||||
|
*/
|
||||||
|
class Discord extends Base implements NotificationInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Send notification to a user
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $user
|
||||||
|
* @param string $eventName
|
||||||
|
* @param array $eventData
|
||||||
|
*/
|
||||||
|
public function notifyUser(array $user, $eventName, array $eventData)
|
||||||
|
{
|
||||||
|
$webhook = $this->userMetadataModel->get($user['id'], 'discord_webhook_url', $this->configModel->get('discord_webhook_url'));
|
||||||
|
$forward_attachments = $this->userMetadataModel->get($user['id'], 'forward_attachments', $this->configModel->get('forward_attachments'));
|
||||||
|
|
||||||
|
if (! empty($webhook)) {
|
||||||
|
if ($eventName === TaskModel::EVENT_OVERDUE) {
|
||||||
|
foreach ($eventData['tasks'] as $task) {
|
||||||
|
$project = $this->projectModel->getById($task['project_id']);
|
||||||
|
$eventData['task'] = $task;
|
||||||
|
$this->sendMessage($webhook, $forward_attachments, $project, $eventName, $eventData);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$project = $this->projectModel->getById($eventData['task']['project_id']);
|
||||||
|
$this->sendMessage($webhook, $forward_attachments, $project, $eventName, $eventData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send notification to a project
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $project
|
||||||
|
* @param string $eventName
|
||||||
|
* @param array $eventData
|
||||||
|
*/
|
||||||
|
public function notifyProject(array $project, $eventName, array $eventData)
|
||||||
|
{
|
||||||
|
$webhook = $this->projectMetadataModel->get($project['id'], 'discord_webhook_url', $this->configModel->get('discord_webhook_url'));
|
||||||
|
$forward_attachments = $this->userMetadataModel->get($user['id'], 'forward_attachments', $this->configModel->get('forward_attachments'));
|
||||||
|
|
||||||
|
if (! empty($webhook)) {
|
||||||
|
$this->sendMessage($webhook, $forward_attachments, $project, $eventName, $eventData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get message to send
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $project
|
||||||
|
* @param string $eventName
|
||||||
|
* @param array $eventData
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getMessage(array $project, $forward_attachments, $eventName, array $eventData)
|
||||||
|
{
|
||||||
|
if ($this->userSession->isLogged()) {
|
||||||
|
$author = $this->helper->user->getFullname();
|
||||||
|
$title = $this->notificationModel->getTitleWithAuthor($author, $eventName, $eventData);
|
||||||
|
} else {
|
||||||
|
$title = $this->notificationModel->getTitleWithoutAuthor($eventName, $eventData);
|
||||||
|
}
|
||||||
|
|
||||||
|
$proj_name = isset($eventData['project_name']) ? $eventData['project_name'] : $eventData['task']['project_name'];
|
||||||
|
$task_title = $eventData['task']['title'];
|
||||||
|
$task_url = $this->helper->url->to('TaskViewController', 'show', array('task_id' => $eventData['task']['id'], 'project_id' => $project['id']), '', true);
|
||||||
|
|
||||||
|
$attachment = '';
|
||||||
|
|
||||||
|
//Build Message
|
||||||
|
|
||||||
|
$message = "[".htmlspecialchars($proj_name, ENT_NOQUOTES | ENT_IGNORE)."]\n";
|
||||||
|
$message .= htmlspecialchars($title, ENT_NOQUOTES | ENT_IGNORE)."\n";
|
||||||
|
|
||||||
|
if ($this->configModel->get('application_url') !== '')
|
||||||
|
{
|
||||||
|
$message .= '📝 <a href="'.$task_url.'">'.htmlspecialchars($task_title, ENT_NOQUOTES | ENT_IGNORE).'</a>';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$message .= htmlspecialchars($task_title, ENT_NOQUOTES | ENT_IGNORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add additional informations
|
||||||
|
|
||||||
|
$description_events = array(TaskModel::EVENT_CREATE, TaskModel::EVENT_UPDATE, TaskModel::EVENT_USER_MENTION);
|
||||||
|
$subtask_events = array(SubtaskModel::EVENT_CREATE, SubtaskModel::EVENT_UPDATE, SubtaskModel::EVENT_DELETE);
|
||||||
|
$comment_events = array(CommentModel::EVENT_UPDATE, CommentModel::EVENT_CREATE, CommentModel::EVENT_DELETE, CommentModel::EVENT_USER_MENTION);
|
||||||
|
|
||||||
|
if (in_array($eventName, $subtask_events)) // For subtask events
|
||||||
|
{
|
||||||
|
$subtask_status = $eventData['subtask']['status'];
|
||||||
|
$subtask_symbol = '';
|
||||||
|
|
||||||
|
if ($subtask_status == SubtaskModel::STATUS_DONE)
|
||||||
|
{
|
||||||
|
$subtask_symbol = '❌ ';
|
||||||
|
}
|
||||||
|
elseif ($subtask_status == SubtaskModel::STATUS_TODO)
|
||||||
|
{
|
||||||
|
$subtask_symbol = '';
|
||||||
|
}
|
||||||
|
elseif ($subtask_status == SubtaskModel::STATUS_INPROGRESS)
|
||||||
|
{
|
||||||
|
$subtask_symbol = '🕘 ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$message .= "\n<b> ↳ ".$subtask_symbol.'</b> <em>"'.htmlspecialchars($eventData['subtask']['title'], ENT_NOQUOTES | ENT_IGNORE).'"</em>';
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif (in_array($eventName, $description_events)) // If description available
|
||||||
|
{
|
||||||
|
if ($eventData['task']['description'] != '')
|
||||||
|
{
|
||||||
|
$message .= "\n✏️ ".'<em>"'.htmlspecialchars($eventData['task']['description'], ENT_NOQUOTES | ENT_IGNORE).'"</em>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif (in_array($eventName, $comment_events)) // If comment available
|
||||||
|
{
|
||||||
|
$message .= "\n💬 ".'<em>"'.htmlspecialchars($eventData['comment']['comment'], ENT_NOQUOTES | ENT_IGNORE).'"</em>';
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif ($eventName === TaskFileModel::EVENT_CREATE and $forward_attachments) // If attachment available
|
||||||
|
{
|
||||||
|
$file_path = getcwd()."/data/files/".$eventData['file']['path'];
|
||||||
|
$file_name = $eventData['file']['name'];
|
||||||
|
$is_image = $eventData['file']['is_image'];
|
||||||
|
|
||||||
|
mkdir(sys_get_temp_dir()."/kanboard_discord_plugin");
|
||||||
|
$attachment = sys_get_temp_dir()."/kanboard_discord_plugin/".clean($file_name);
|
||||||
|
file_put_contents($attachment, file_get_contents($file_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ($this->configModel->get('application_url') !== '') {
|
||||||
|
$message .= ' - <';
|
||||||
|
$message .= $this->helper->url->to('TaskViewController', 'show', array('task_id' => $eventData['task']['id'], 'project_id' => $project['id']), '', true);
|
||||||
|
$message .= '|'.t('view the task on Kanboard').'>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'text' => $message,
|
||||||
|
'attachment' => $attachment,
|
||||||
|
'username' => 'Kanboard',
|
||||||
|
'icon_url' => 'https://raw.githubusercontent.com/kanboard/kanboard/master/assets/img/favicon.png',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send message to Discord
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @param string $webhook
|
||||||
|
* @param string $channel
|
||||||
|
* @param array $project
|
||||||
|
* @param string $eventName
|
||||||
|
* @param array $eventData
|
||||||
|
*/
|
||||||
|
protected function sendMessage($webhook, $forward_attachments, array $project, $eventName, array $eventData)
|
||||||
|
{
|
||||||
|
$payload = $this->getMessage($project, $forward_attachments, $eventName, $eventData);
|
||||||
|
|
||||||
|
$this->httpClient->postJsonAsync($webhook, $payload);
|
||||||
|
}
|
||||||
|
}
|
55
Plugin.php
Normal file
55
Plugin.php
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Plugin\Discord;
|
||||||
|
|
||||||
|
use Kanboard\Core\Translator;
|
||||||
|
use Kanboard\Core\Plugin\Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discord Plugin
|
||||||
|
*
|
||||||
|
* @package discord
|
||||||
|
* @author Ryonez Coruscare
|
||||||
|
*/
|
||||||
|
class Plugin extends Base
|
||||||
|
{
|
||||||
|
public function initialize()
|
||||||
|
{
|
||||||
|
$this->template->hook->attach('template:config:integrations', 'discord:config/integration');
|
||||||
|
$this->template->hook->attach('template:project:integrations', 'discord:project/integration');
|
||||||
|
$this->template->hook->attach('template:user:integrations', 'discord:user/integration');
|
||||||
|
|
||||||
|
$this->userNotificationTypeModel->setType('discord', t('Discord'), '\Kanboard\Plugin\Discord\Notification\Discord');
|
||||||
|
$this->projectNotificationTypeModel->setType('discord', t('Discord'), '\Kanboard\Plugin\Discord\Notification\Discord');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onStartup()
|
||||||
|
{
|
||||||
|
Translator::load($this->languageModel->getCurrentLanguage(), __DIR__.'/Locale');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPluginDescription()
|
||||||
|
{
|
||||||
|
return 'Receive notifications on Discord';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPluginAuthor()
|
||||||
|
{
|
||||||
|
return 'Ryonez Coruscare';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPluginVersion()
|
||||||
|
{
|
||||||
|
return '0.0.1';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPluginHomepage()
|
||||||
|
{
|
||||||
|
return 'https://codelabs.alteria.xyz/ryonez/kanboard-discord';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCompatibleVersion()
|
||||||
|
{
|
||||||
|
return '>=1.0.37';
|
||||||
|
}
|
||||||
|
}
|
53
README.md
Normal file
53
README.md
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
Slack plugin for Kanboard
|
||||||
|
=========================
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/kanboard/plugin-slack.svg?branch=master)](https://travis-ci.org/kanboard/plugin-slack)
|
||||||
|
|
||||||
|
Receive Kanboard notifications on Slack.
|
||||||
|
|
||||||
|
Author
|
||||||
|
------
|
||||||
|
|
||||||
|
- Frederic Guillot
|
||||||
|
- License MIT
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
- Kanboard >= 1.0.37
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
You have the choice between 3 methods:
|
||||||
|
|
||||||
|
1. Install the plugin from the Kanboard plugin manager in one click
|
||||||
|
2. Download the zip file and decompress everything under the directory `plugins/Slack`
|
||||||
|
3. Clone this repository into the folder `plugins/Slack`
|
||||||
|
|
||||||
|
Note: Plugin folder is case-sensitive.
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Firstly, you have to generate a new webhook url in Discord (**Server or Channel Settings > Webhooks**).
|
||||||
|
|
||||||
|
You can define only one webhook url (**Settings > Integrations > Slack**) for each project and user.
|
||||||
|
|
||||||
|
### Receive individual user notifications
|
||||||
|
|
||||||
|
- Go to your user profile then choose **Integrations > Discord**
|
||||||
|
- Copy and paste the webhook url from Slack or leave it blank if you want to use the global webhook url
|
||||||
|
- Use `@username` to receive direct message to your user
|
||||||
|
- Enable Discord in your user notifications **Notifications > Discord**
|
||||||
|
|
||||||
|
### Receive project notifications to a room
|
||||||
|
|
||||||
|
- Go to the project settings then choose **Integrations > Discord**
|
||||||
|
- Copy and paste the webhook url from Discord or leave it blank if you want to use the global webhook url
|
||||||
|
- Enable Discord in your project notifications **Notifications > Discord**
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
- Enable the debug mode
|
||||||
|
- All connection errors with the Discord API are recorded in the log files `data/debug.log` or syslog
|
11
Template/config/integration.php
Normal file
11
Template/config/integration.php
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<h3><i class="fa fa-discord fa-fw"></i>Slack</h3>
|
||||||
|
<div class="panel">
|
||||||
|
<?= $this->form->label(t('Webhook URL'), 'discord_webhook_url') ?>
|
||||||
|
<?= $this->form->text('discord_webhook_url', $values) ?>
|
||||||
|
|
||||||
|
<p class="form-help"><a href="https://codelabs.alteria.xyz/ryonez/kanboard-discord#configuration" target="_blank"><?= t('Help on Discord integration') ?></a></p>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
11
Template/project/integration.php
Normal file
11
Template/project/integration.php
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<h3><i class="fa fa-discord fa-fw"></i>Slack</h3>
|
||||||
|
<div class="panel">
|
||||||
|
<?= $this->form->label(t('Webhook URL'), 'discord') ?>
|
||||||
|
<?= $this->form->text('discord_webhook_url', $values) ?>
|
||||||
|
|
||||||
|
<p class="form-help"><a href="https://codelabs.alteria.xyz/ryonez/kanboard-discord#configuration" target="_blank"><?= t('Help on Discord integration') ?></a></p>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
11
Template/user/integration.php
Normal file
11
Template/user/integration.php
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<h3><i class="fa fa-discord fa-fw"></i>Slack</h3>
|
||||||
|
<div class="panel">
|
||||||
|
<?= $this->form->label(t('Webhook URL'), 'discord_webhook_url') ?>
|
||||||
|
<?= $this->form->text('discord_webhook_url', $values) ?>
|
||||||
|
|
||||||
|
<p class="form-help"><a href="https://codelabs.alteria.xyz/ryonez/kanboard-discord#configuration" target="_blank"><?= t('Help on Discord integration') ?></a></p>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<input type="submit" value="<?= t('Save') ?>" class="btn btn-blue"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
20
Test/PluginTest.php
Normal file
20
Test/PluginTest.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'tests/units/Base.php';
|
||||||
|
|
||||||
|
use Kanboard\Plugin\Discord\Plugin;
|
||||||
|
|
||||||
|
class PluginTest extends Base
|
||||||
|
{
|
||||||
|
public function testPlugin()
|
||||||
|
{
|
||||||
|
$plugin = new Plugin($this->container);
|
||||||
|
$this->assertSame(null, $plugin->initialize());
|
||||||
|
$this->assertSame(null, $plugin->onStartup());
|
||||||
|
$this->assertNotEmpty($plugin->getPluginName());
|
||||||
|
$this->assertNotEmpty($plugin->getPluginDescription());
|
||||||
|
$this->assertNotEmpty($plugin->getPluginAuthor());
|
||||||
|
$this->assertNotEmpty($plugin->getPluginVersion());
|
||||||
|
$this->assertNotEmpty($plugin->getPluginHomepage());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue