/trunk/Discord.php |
@@ -1,4 +1,5 @@ |
<?php |
|
/** |
* Discord Integration |
* Copyright (C) Robin van Nunen (robin@vnunen.nl) for Discord modification |
@@ -32,21 +33,19 @@ |
$this->requires = array( |
'MantisCore' => '1.3.0', |
); |
$this->author = 'Robin van Nunen'; |
$this->contact = 'robin@vnunen.nl'; |
$this->author = 'Robin van Nunen & Wizardry and Steamworks'; |
$this->contact = 'robin@vnunen.nl / office@grimore.org'; |
$this->url = 'https://github.com/TechGuard/MantisBT-Discord'; |
} |
|
function install() |
{ |
if(version_compare(PHP_VERSION, '5.3.0', '<')) |
{ |
if (version_compare(PHP_VERSION, '5.3.0', '<')) { |
plugin_error(ERROR_PHP_VERSION, ERROR); |
|
return false; |
} |
if(!extension_loaded('curl')) |
{ |
if (!extension_loaded('curl')) { |
plugin_error(ERROR_NO_CURL, ERROR); |
|
return false; |
@@ -96,8 +95,7 @@ |
|
function bugnote_add_form($event, $bug_id) |
{ |
if($_SERVER['PHP_SELF'] !== '/bug_update_page.php') |
{ |
if ($_SERVER['PHP_SELF'] !== '/bug_update_page.php') { |
return; |
} |
echo '<tr>'; |
@@ -119,17 +117,38 @@ |
$summary = $this->format_summary($bug); |
$reporter = $this->get_user_name(auth_get_current_user_id()); |
$handler = $this->format_value($bug, 'handler_id'); |
$msg = sprintf(plugin_lang_get($event === 'EVENT_REPORT_BUG' ? 'bug_created' : 'bug_updated'), |
$project, $reporter, $url, $summary, $handler |
// TODO: The page anchors do not work. |
$msg = sprintf( |
plugin_lang_get($event === 'EVENT_REPORT_BUG' ? 'bug_created' : 'bug_updated'), |
$project, |
$reporter, |
$url, |
$summary, |
$handler |
); |
$this->notify($msg, $this->get_webhook($project), $this->get_attachment($bug)); |
|
$attachments = array('color' => hexdec('ef2929')); |
$t_columns = (array) plugin_config_get('columns'); |
foreach ($t_columns as $t_column) { |
$title = column_get_title($t_column); |
$value = $this->format_value($bug, $t_column); |
if ($title && $value) { |
$attachments['fallback'] .= $title . ': ' . $value . "\n"; |
$attachments['fields'][] = array( |
'name' => $title, |
'value' => $value, |
'inline' => !column_is_extended($t_column), |
); |
} |
} |
|
$this->notify($msg, $this->get_webhook($project), $attachments); |
lang_pop(); |
} |
|
function bug_report($event, $bug, $bug_id) |
{ |
if(plugin_config_get('hook_bug_report', false)) |
{ |
if (plugin_config_get('hook_bug_report', false)) { |
$this->bug_report_update($event, $bug, $bug_id); |
} |
} |
@@ -136,8 +155,7 @@ |
|
function bug_update($event, $bug_existing, $bug_updated) |
{ |
if(plugin_config_get('hook_bug_update', false)) |
{ |
if (plugin_config_get('hook_bug_update', false)) { |
$this->bug_report_update($event, $bug_updated, $bug_updated->id); |
} |
} |
@@ -145,8 +163,7 @@ |
function bug_action($event, $action, $bug_id) |
{ |
$this->skip = $this->skip || gpc_get_bool('slack_skip') || plugin_config_get('skip_bulk'); |
if($action !== 'DELETE') |
{ |
if ($action !== 'DELETE') { |
$bug = bug_get($bug_id); |
$this->bug_update('EVENT_UPDATE_BUG', null, $bug); |
} |
@@ -154,8 +171,7 @@ |
|
function bug_deleted($event, $bug_id) |
{ |
if(!plugin_config_get('hook_bug_deleted', false)) |
{ |
if (!plugin_config_get('hook_bug_deleted', false)) { |
return; |
} |
|
@@ -165,8 +181,11 @@ |
$project = project_get_name($bug->project_id); |
$reporter = $this->get_user_name(auth_get_current_user_id()); |
$summary = $this->format_summary($bug); |
// TODO: The page anchors do not work. |
$msg = sprintf(plugin_lang_get('bug_deleted'), $project, $reporter, $summary); |
$this->notify($msg, $this->get_webhook($project)); |
$attachments = array('color' => hexdec('ef2929')); |
$attachments['title'] = $msg; |
$this->notify(null, $this->get_webhook($project), $attachments); |
lang_pop(); |
} |
|
@@ -173,8 +192,7 @@ |
function bugnote_add_edit($event, $bug_id, $bugnote_id) |
{ |
$type = ($event === 'EVENT_BUGNOTE_ADD') ? 'add' : 'edit'; |
if(!plugin_config_get('hook_bugnote_' . $type, false)) |
{ |
if (!plugin_config_get('hook_bugnote_' . $type, false)) { |
return; |
} |
|
@@ -187,26 +205,23 @@ |
$summary = $this->format_summary($bug); |
$reporter = $this->get_user_name(auth_get_current_user_id()); |
$note = bugnote_get_text($bugnote_id); |
$msg = sprintf(plugin_lang_get($event === 'EVENT_BUGNOTE_ADD' ? 'bugnote_created' : 'bugnote_updated'), |
$project, $reporter, $url, $summary |
// TODO: The page anchors do not work. |
$msg = sprintf( |
plugin_lang_get($event === 'EVENT_BUGNOTE_ADD' ? 'bugnote_created' : 'bugnote_updated'), |
$project, |
$reporter, |
$url, |
$summary |
); |
$this->notify($msg, $this->get_webhook($project), $this->get_text_attachment($this->bbcode_to_slack($note))); |
$attachments = array('color' => hexdec("3366ff")); |
$attachments['title'] = $msg . ' : ' . $this->bbcode_to_discord($note); |
$this->notify(null, $this->get_webhook($project), $attachments); |
lang_pop(); |
} |
|
function get_text_attachment($text) |
{ |
$attachment = array('color' => '#3AA3E3', 'mrkdwn_in' => array('pretext', 'text', 'fields')); |
$attachment['fallback'] = "$text\n"; |
$attachment['text'] = $text; |
|
return $attachment; |
} |
|
function bugnote_deleted($event, $bug_id, $bugnote_id) |
{ |
if(!plugin_config_get('hook_bugnote_deleted', false)) |
{ |
if (!plugin_config_get('hook_bugnote_deleted', false)) { |
return; |
} |
|
@@ -218,8 +233,11 @@ |
$url = string_get_bug_view_url_with_fqdn($bug_id); |
$summary = $this->format_summary($bug); |
$reporter = $this->get_user_name(auth_get_current_user_id()); |
// TODO: The page anchors do not work. |
$msg = sprintf(plugin_lang_get('bugnote_deleted'), $project, $reporter, $url, $summary); |
$this->notify($msg, $this->get_webhook($project)); |
$attachments = array('color' => hexdec("3366ff")); |
$attachments['title'] = $msg; |
$this->notify(null, $this->get_webhook($project), $attachments); |
lang_pop(); |
} |
|
@@ -232,113 +250,116 @@ |
|
function format_text($bug, $text) |
{ |
$t = string_display_line_links($this->bbcode_to_slack($text)); |
$t = string_display_line_links($this->bbcode_to_discord($text)); |
|
return strip_tags(html_entity_decode($t)); |
} |
|
function get_attachment($bug) |
function format_value($bug, $field_name) |
{ |
if($bug->status == FEEDBACK) |
{ |
$color = '#75507b'; |
} |
else if($bug->status == ACKNOWLEDGED) |
{ |
$color = '#f57900'; |
} |
else if($bug->status == CONFIRMED) |
{ |
$color = '#fce94f'; |
} |
else if($bug->status == ASSIGNED) |
{ |
$color = '#729fcf'; |
} |
else if($bug->status == RESOLVED) |
{ |
$color = '#8ae234'; |
} |
else if($bug->status == CLOSED) |
{ |
$color = '#8ae234'; |
} |
else |
{ |
$color = '#ef2929'; |
} |
|
$attachment = array('fallback' => '', 'color' => $color, 'mrkdwn_in' => array('pretext', 'text', 'fields')); |
$t_columns = (array) plugin_config_get('columns'); |
foreach($t_columns as $t_column) |
{ |
$title = column_get_title($t_column); |
$value = $this->format_value($bug, $t_column); |
if($title && $value) |
{ |
$attachment['fallback'] .= $title . ': ' . $value . "\n"; |
$attachment['fields'][] = array( |
'title' => $title, |
'value' => $value, |
'short' => !column_is_extended($t_column), |
); |
} |
} |
|
return $attachment; |
} |
|
function format_value($bug, $field_name) { |
$self = $this; |
$values = array( |
'id' => function($bug) { return sprintf('<%s|%s>', string_get_bug_view_url_with_fqdn($bug->id), $bug->id); }, |
'project_id' => function($bug) { return project_get_name($bug->project_id); }, |
'reporter_id' => function($bug) { return $this->get_user_name($bug->reporter_id, true); }, |
'handler_id' => function($bug) { return empty($bug->handler_id) ? plugin_lang_get('no_user') : $this->get_user_name($bug->handler_id, true); }, |
'duplicate_id' => function($bug) { return sprintf('<%s|%s>', string_get_bug_view_url_with_fqdn($bug->duplicate_id), $bug->duplicate_id); }, |
'priority' => function($bug) { return get_enum_element( 'priority', $bug->priority ); }, |
'severity' => function($bug) { return get_enum_element( 'severity', $bug->severity ); }, |
'reproducibility' => function($bug) { return get_enum_element( 'reproducibility', $bug->reproducibility ); }, |
'status' => function($bug) { return get_enum_element( 'status', $bug->status ); }, |
'resolution' => function($bug) { return get_enum_element( 'resolution', $bug->resolution ); }, |
'projection' => function($bug) { return get_enum_element( 'projection', $bug->projection ); }, |
'category_id' => function($bug) { return category_full_name( $bug->category_id, false ); }, |
'eta' => function($bug) { return get_enum_element( 'eta', $bug->eta ); }, |
'view_state' => function($bug) { return $bug->view_state == VS_PRIVATE ? lang_get('private') : lang_get('public'); }, |
'sponsorship_total' => function($bug) { return sponsorship_format_amount( $bug->sponsorship_total ); }, |
'os' => function($bug) { return $bug->os; }, |
'os_build' => function($bug) { return $bug->os_build; }, |
'platform' => function($bug) { return $bug->platform; }, |
'version' => function($bug) { return $bug->version; }, |
'fixed_in_version' => function($bug) { return $bug->fixed_in_version; }, |
'target_version' => function($bug) { return $bug->target_version; }, |
'build' => function($bug) { return $bug->build; }, |
'summary' => function($bug) use($self) { return $self->format_summary($bug); }, |
'last_updated' => function($bug) { return date( config_get( 'short_date_format' ), $bug->last_updated ); }, |
'date_submitted' => function($bug) { return date( config_get( 'short_date_format' ), $bug->date_submitted ); }, |
'due_date' => function($bug) { return date( config_get( 'short_date_format' ), $bug->due_date ); }, |
'description' => function($bug) use($self) { return $self->format_text( $bug, $bug->description ); }, |
'steps_to_reproduce' => function($bug) use($self) { return $self->format_text( $bug, $bug->steps_to_reproduce ); }, |
'additional_information' => function($bug) use($self) { return $self->format_text( $bug, $bug->additional_information ); }, |
'id' => function ($bug) { |
return sprintf('<%s|%s>', string_get_bug_view_url_with_fqdn($bug->id), $bug->id); |
}, |
'project_id' => function ($bug) { |
return project_get_name($bug->project_id); |
}, |
'reporter_id' => function ($bug) { |
return $this->get_user_name($bug->reporter_id, true); |
}, |
'handler_id' => function ($bug) { |
return empty($bug->handler_id) ? plugin_lang_get('no_user') : $this->get_user_name($bug->handler_id, true); |
}, |
'duplicate_id' => function ($bug) { |
return sprintf('<%s|%s>', string_get_bug_view_url_with_fqdn($bug->duplicate_id), $bug->duplicate_id); |
}, |
'priority' => function ($bug) { |
return get_enum_element('priority', $bug->priority); |
}, |
'severity' => function ($bug) { |
return get_enum_element('severity', $bug->severity); |
}, |
'reproducibility' => function ($bug) { |
return get_enum_element('reproducibility', $bug->reproducibility); |
}, |
'status' => function ($bug) { |
return get_enum_element('status', $bug->status); |
}, |
'resolution' => function ($bug) { |
return get_enum_element('resolution', $bug->resolution); |
}, |
'projection' => function ($bug) { |
return get_enum_element('projection', $bug->projection); |
}, |
'category_id' => function ($bug) { |
return category_full_name($bug->category_id, false); |
}, |
'eta' => function ($bug) { |
return get_enum_element('eta', $bug->eta); |
}, |
'view_state' => function ($bug) { |
return $bug->view_state == VS_PRIVATE ? lang_get('private') : lang_get('public'); |
}, |
'sponsorship_total' => function ($bug) { |
return sponsorship_format_amount($bug->sponsorship_total); |
}, |
'os' => function ($bug) { |
return $bug->os; |
}, |
'os_build' => function ($bug) { |
return $bug->os_build; |
}, |
'platform' => function ($bug) { |
return $bug->platform; |
}, |
'version' => function ($bug) { |
return $bug->version; |
}, |
'fixed_in_version' => function ($bug) { |
return $bug->fixed_in_version; |
}, |
'target_version' => function ($bug) { |
return $bug->target_version; |
}, |
'build' => function ($bug) { |
return $bug->build; |
}, |
'summary' => function ($bug) use ($self) { |
return $self->format_summary($bug); |
}, |
'last_updated' => function ($bug) { |
return date(config_get('short_date_format'), $bug->last_updated); |
}, |
'date_submitted' => function ($bug) { |
return date(config_get('short_date_format'), $bug->date_submitted); |
}, |
'due_date' => function ($bug) { |
return date(config_get('short_date_format'), $bug->due_date); |
}, |
'description' => function ($bug) use ($self) { |
return $self->format_text($bug, $bug->description); |
}, |
'steps_to_reproduce' => function ($bug) use ($self) { |
return $self->format_text($bug, $bug->steps_to_reproduce); |
}, |
'additional_information' => function ($bug) use ($self) { |
return $self->format_text($bug, $bug->additional_information); |
}, |
); |
// Discover custom fields. |
$t_related_custom_field_ids = custom_field_get_linked_ids($bug->project_id); |
foreach($t_related_custom_field_ids as $t_id) |
{ |
foreach ($t_related_custom_field_ids as $t_id) { |
$t_def = custom_field_get_definition($t_id); |
$values[ 'custom_' . $t_def['name'] ] = function($bug) use ($t_id) |
{ |
$values['custom_' . $t_def['name']] = function ($bug) use ($t_id) { |
return custom_field_get_value($t_id, $bug->id); |
}; |
} |
if(isset($values[ $field_name ])) |
{ |
if (isset($values[$field_name])) { |
$func = $values[ $field_name ]; |
|
return $func($bug); |
} |
else |
{ |
} else { |
return false; |
} |
} |
@@ -350,53 +371,58 @@ |
return array_key_exists($project, $webhooks) ? $webhooks[ $project ] : plugin_config_get('url_webhook'); |
} |
|
function notify($msg, $webhook, $attachment = false) |
function notify($msg, $webhook, $attachments) |
{ |
if($this->skip) |
{ |
if ($this->skip) { |
return; |
} |
if(empty($webhook)) |
{ |
if (empty($webhook)) { |
return; |
} |
$url = sprintf('%s', trim($webhook)); |
if(substr($url, -strlen('/slack')) != '/slack') |
{ |
$url .= '/slack'; |
|
$payload['content'] = $msg; |
if ($attachments != null) { |
$payload['embeds'] = array($attachments); |
} |
|
$ch = curl_init(); |
curl_setopt($ch, CURLOPT_URL, $url); |
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
$payload = array( |
'text' => $msg, |
); |
if($attachment) |
{ |
$payload['attachments'] = array($attachment); |
} |
$data = array('payload' => json_encode($payload)); |
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); |
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); |
curl_setopt($ch, CURLOPT_TIMEOUT, 5); |
$ch = curl_init($webhook); |
curl_setopt($ch, CURLOPT_POST, 1); |
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json; charset=utf-8']); |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
curl_setopt($ch, CURLOPT_VERBOSE, 1); |
curl_setopt($ch, CURLOPT_HEADER, 1); |
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); |
$result = curl_exec($ch); |
if($result !== 'ok') |
{ |
trigger_error(curl_errno($ch) . ': ' . curl_error($ch), E_USER_WARNING); |
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) !== 204 && $result !== 'ok') { |
trigger_error(curl_errno($ch) . ': ' . curl_error($ch) . ": ", E_USER_WARNING); |
echo '<div class="center"><pre>' . json_encode($payload, JSON_PRETTY_PRINT) . '</pre></div>'; |
echo '<div class="center">' . $result . '</div>'; |
plugin_error('ERROR_CURL', E_USER_ERROR); |
} |
curl_close($ch); |
} |
|
function bbcode_to_slack($bbtext) |
function bbcode_to_discord($bbtext) |
{ |
$bbextended = array( |
"/\[code(.*?)\](.*?)\[\/code\]/is" => "`$2`", |
"/\[list(.*?)\](.*?)\[\/list\]/is" => "$2", |
"/\[color(.*?)\](.*?)\[\/color\]/is" => "$2", |
"/\[size=(.*?)\](.*?)\[\/size\]/is" => "$2", |
"/\[highlight(.*?)\](.*?)\[\/highlight\]/is" => "$2", |
"/\[url](.*?)\[\/url]/i" => "$1", |
"/\[url=(.*?)\](.*?)\[\/url\]/i" => "$1", |
"/\[email=(.*?)\](.*?)\[\/email\]/i" => "$1", |
"/\[img\]([^[]*)\[\/img\]/i" => "$1", |
); |
foreach ($bbextended as $match => $replacement) { |
$bbtext = preg_replace($match, $replacement, $bbtext); |
} |
$bbtags = array( |
'[b]' => '*','[/b]' => '* ', |
'[i]' => '_','[/i]' => '_ ', |
'[u]' => '_','[/u]' => '_ ', |
'[s]' => '~','[/s]' => '~ ', |
'[b]' => '*', '[/b]' => '** ', |
'[i]' => '*', '[/i]' => '* ', |
'[u]' => '__', '[/u]' => '__ ', |
'[s]' => '~~', '[/s]' => '~~ ', |
'[sup]' => '','[/sup]' => '', |
'[sub]' => '','[/sub]' => '', |
|
@@ -411,35 +437,21 @@ |
'[justify]' => '','[/justify]' => '', |
); |
$bbtext = str_ireplace(array_keys($bbtags), array_values($bbtags), $bbtext); |
$bbextended = array( |
"/\[code(.*?)\](.*?)\[\/code\]/is" => "```$2```", |
"/\[color(.*?)\](.*?)\[\/color\]/is" => "$2", |
"/\[size=(.*?)\](.*?)\[\/size\]/is" => "$2", |
"/\[highlight(.*?)\](.*?)\[\/highlight\]/is" => "$2", |
"/\[url](.*?)\[\/url]/i" => "<$1>", |
"/\[url=(.*?)\](.*?)\[\/url\]/i" => "<$1|$2>", |
"/\[email=(.*?)\](.*?)\[\/email\]/i" => "<mailto:$1|$2>", |
"/\[img\]([^[]*)\[\/img\]/i" => "<$1>", |
); |
foreach($bbextended as $match => $replacement) |
{ |
$bbtext = preg_replace($match, $replacement, $bbtext); |
} |
$bbtext = preg_replace_callback("/\[quote(=)?(.*?)\](.*?)\[\/quote\]/is", |
function($matches) |
{ |
if(!empty($matches[2])) |
{ |
$bbtext = preg_replace_callback( |
"/\[quote(=)?(.*?)\](.*?)\[\/quote\]/is", |
function ($matches) { |
if (!empty($matches[2])) { |
$result = "\n> _*" . $matches[2] . "* wrote:_\n> \n"; |
} |
$lines = explode("\n", $matches[3]); |
foreach($lines as $line) |
{ |
foreach ($lines as $line) { |
$result .= "> " . $line . "\n"; |
} |
|
return $result; |
}, $bbtext); |
}, |
$bbtext |
); |
|
return $bbtext; |
} |
@@ -448,16 +460,13 @@ |
{ |
$user = user_get_row($user_id); |
$username = $user['username']; |
if(!$discord || !plugin_config_get('link_names')) |
{ |
if (!$discord || !plugin_config_get('link_names')) { |
return $username; |
} |
$usernames = plugin_config_get('usernames'); |
if(array_key_exists($username, $usernames)) |
{ |
if (array_key_exists($username, $usernames)) { |
return '<@' . $usernames[$username] . '>'; |
} |
return $username; |
} |
|
} |
} |