mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 14:52:41 +01:00
Add a basic chatlog
Summary: This is pretty simple and unpolished, but it's getting pretty big and it seems like a reasonable starting point. - Log chat in various "channels". - Conduit record and query methods. - IRCBot integration for IRC logging Major TODO: - Web UI is really unpolished and has no search, paging, anchor-linking, etc. Basically all presentation stuff, though. - I think the bot should have a map of channels to log with channel aliases? - The "channels" should probably be in a separate table. - The "authors" should probably be correlated to Phabricator accounts somehow, where possible. Test Plan: Used phabotlocal to log #phabricator. Reviewers: kdeggelman, btrahan, Koolvin Reviewed By: btrahan CC: aran, epriestley Maniphest Tasks: T837 Differential Revision: https://secure.phabricator.com/D1625
This commit is contained in:
parent
50363695bb
commit
7200040479
35 changed files with 911 additions and 12 deletions
|
@ -8,6 +8,7 @@
|
|||
"handlers" : [
|
||||
"PhabricatorIRCProtocolHandler",
|
||||
"PhabricatorIRCObjectNameHandler",
|
||||
"PhabricatorIRCLogHandler",
|
||||
"PhabricatorIRCDifferentialNotificationHandler"
|
||||
],
|
||||
|
||||
|
|
11
resources/sql/patches/106.chatlog.sql
Normal file
11
resources/sql/patches/106.chatlog.sql
Normal file
|
@ -0,0 +1,11 @@
|
|||
CREATE DATABASE IF NOT EXISTS phabricator_chatlog;
|
||||
CREATE TABLE phabricator_chatlog.chatlog_event (
|
||||
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
channel VARCHAR(64) BINARY NOT NULL,
|
||||
epoch INT UNSIGNED NOT NULL,
|
||||
author VARCHAR(64) BINARY NOT NULL,
|
||||
type VARCHAR(4) NOT NULL,
|
||||
message LONGBLOB NOT NULL,
|
||||
loggedByPHID VARCHAR(64) BINARY NOT NULL,
|
||||
KEY (channel, epoch)
|
||||
);
|
|
@ -1330,6 +1330,15 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/herald/PathTypeahead.js',
|
||||
),
|
||||
'phabricator-chatlog-css' =>
|
||||
array(
|
||||
'uri' => '/res/a5aa9eef/rsrc/css/application/chatlog/chatlog.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/chatlog/chatlog.css',
|
||||
),
|
||||
'phabricator-content-source-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/8c738a93/rsrc/css/application/contentsource/content-source-view.css',
|
||||
|
@ -1508,6 +1517,17 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/css/core/remarkup.css',
|
||||
),
|
||||
0 =>
|
||||
array(
|
||||
'uri' => '/res/b6096fdd/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-uri',
|
||||
1 => 'javelin-php-serializer',
|
||||
),
|
||||
'disk' => '/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
),
|
||||
'phabricator-search-results-css' =>
|
||||
array(
|
||||
'uri' => '/res/f8a86e27/rsrc/css/application/search/search-results.css',
|
||||
|
@ -1529,17 +1549,6 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/core/ShapedRequest.js',
|
||||
),
|
||||
0 =>
|
||||
array(
|
||||
'uri' => '/res/b6096fdd/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-uri',
|
||||
1 => 'javelin-php-serializer',
|
||||
),
|
||||
'disk' => '/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
),
|
||||
'phabricator-slowvote-css' =>
|
||||
array(
|
||||
'uri' => '/res/94d20443/rsrc/css/application/slowvote/slowvote.css',
|
||||
|
|
|
@ -104,6 +104,9 @@ phutil_register_library_map(array(
|
|||
'ConduitAPIResponse' => 'applications/conduit/protocol/response',
|
||||
'ConduitAPI_arcanist_Method' => 'applications/conduit/method/arcanist/base',
|
||||
'ConduitAPI_arcanist_projectinfo_Method' => 'applications/conduit/method/arcanist/projectinfo',
|
||||
'ConduitAPI_chatlog_Method' => 'applications/conduit/method/chatlog/base',
|
||||
'ConduitAPI_chatlog_query_Method' => 'applications/conduit/method/chatlog/query',
|
||||
'ConduitAPI_chatlog_record_Method' => 'applications/conduit/method/chatlog/record',
|
||||
'ConduitAPI_conduit_connect_Method' => 'applications/conduit/method/conduit/connect',
|
||||
'ConduitAPI_conduit_getcertificate_Method' => 'applications/conduit/method/conduit/getcertificate',
|
||||
'ConduitAPI_conduit_ping_Method' => 'applications/conduit/method/conduit/ping',
|
||||
|
@ -437,6 +440,14 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuthController' => 'applications/auth/controller/base',
|
||||
'PhabricatorCalendarBrowseController' => 'applications/calendar/controller/browse',
|
||||
'PhabricatorCalendarController' => 'applications/calendar/controller/base',
|
||||
'PhabricatorChatLogChannelListController' => 'applications/chatlog/controller/channellist',
|
||||
'PhabricatorChatLogChannelLogController' => 'applications/chatlog/controller/channellog',
|
||||
'PhabricatorChatLogConstants' => 'applications/chatlog/constants/base',
|
||||
'PhabricatorChatLogController' => 'applications/chatlog/controller/base',
|
||||
'PhabricatorChatLogDAO' => 'applications/chatlog/storage/base',
|
||||
'PhabricatorChatLogEvent' => 'applications/chatlog/storage/event',
|
||||
'PhabricatorChatLogEventType' => 'applications/chatlog/constants/eventtype',
|
||||
'PhabricatorChatLogQuery' => 'applications/chatlog/query',
|
||||
'PhabricatorConduitAPIController' => 'applications/conduit/controller/api',
|
||||
'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/token',
|
||||
'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/connectionlog',
|
||||
|
@ -544,6 +555,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorIRCBot' => 'infrastructure/daemon/irc/bot',
|
||||
'PhabricatorIRCDifferentialNotificationHandler' => 'infrastructure/daemon/irc/handler/differentialnotification',
|
||||
'PhabricatorIRCHandler' => 'infrastructure/daemon/irc/handler/base',
|
||||
'PhabricatorIRCLogHandler' => 'infrastructure/daemon/irc/handler/log',
|
||||
'PhabricatorIRCMessage' => 'infrastructure/daemon/irc/message',
|
||||
'PhabricatorIRCObjectNameHandler' => 'infrastructure/daemon/irc/handler/objectname',
|
||||
'PhabricatorIRCProtocolHandler' => 'infrastructure/daemon/irc/handler/protocol',
|
||||
|
@ -919,6 +931,9 @@ phutil_register_library_map(array(
|
|||
'CelerityResourceGraph' => 'AbstractDirectedGraph',
|
||||
'ConduitAPI_arcanist_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_arcanist_projectinfo_Method' => 'ConduitAPI_arcanist_Method',
|
||||
'ConduitAPI_chatlog_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_chatlog_query_Method' => 'ConduitAPI_chatlog_Method',
|
||||
'ConduitAPI_chatlog_record_Method' => 'ConduitAPI_chatlog_Method',
|
||||
'ConduitAPI_conduit_connect_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_conduit_getcertificate_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_conduit_ping_Method' => 'ConduitAPIMethod',
|
||||
|
@ -1177,6 +1192,12 @@ phutil_register_library_map(array(
|
|||
'PhabricatorAuthController' => 'PhabricatorController',
|
||||
'PhabricatorCalendarBrowseController' => 'PhabricatorCalendarController',
|
||||
'PhabricatorCalendarController' => 'PhabricatorController',
|
||||
'PhabricatorChatLogChannelListController' => 'PhabricatorChatLogController',
|
||||
'PhabricatorChatLogChannelLogController' => 'PhabricatorChatLogController',
|
||||
'PhabricatorChatLogController' => 'PhabricatorController',
|
||||
'PhabricatorChatLogDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorChatLogEvent' => 'PhabricatorChatLogDAO',
|
||||
'PhabricatorChatLogEventType' => 'PhabricatorChatLogConstants',
|
||||
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
|
||||
'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO',
|
||||
'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',
|
||||
|
@ -1267,6 +1288,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController',
|
||||
'PhabricatorIRCBot' => 'PhabricatorDaemon',
|
||||
'PhabricatorIRCDifferentialNotificationHandler' => 'PhabricatorIRCHandler',
|
||||
'PhabricatorIRCLogHandler' => 'PhabricatorIRCHandler',
|
||||
'PhabricatorIRCObjectNameHandler' => 'PhabricatorIRCHandler',
|
||||
'PhabricatorIRCProtocolHandler' => 'PhabricatorIRCHandler',
|
||||
'PhabricatorInfrastructureTestCase' => 'PhabricatorTestCase',
|
||||
|
|
|
@ -401,6 +401,13 @@ class AphrontDefaultApplicationConfiguration
|
|||
),
|
||||
'lease/$' => 'DrydockLeaseListController',
|
||||
),
|
||||
|
||||
'/chatlog/' => array(
|
||||
'$' =>
|
||||
'PhabricatorChatLogChannelListController',
|
||||
'channel/(?P<channel>[^/]+)/$' =>
|
||||
'PhabricatorChatLogChannelLogController',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
abstract class PhabricatorChatLogConstants {
|
||||
|
||||
}
|
10
src/applications/chatlog/constants/base/__init__.php
Normal file
10
src/applications/chatlog/constants/base/__init__.php
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorChatLogConstants.php');
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorChatLogEventType
|
||||
extends PhabricatorChatLogConstants {
|
||||
|
||||
const TYPE_MESSAGE = 'mesg';
|
||||
|
||||
}
|
12
src/applications/chatlog/constants/eventtype/__init__.php
Normal file
12
src/applications/chatlog/constants/eventtype/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/chatlog/constants/base');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorChatLogEventType.php');
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
abstract class PhabricatorChatLogController extends PhabricatorController {
|
||||
|
||||
public function buildStandardPageResponse($view, array $data) {
|
||||
$page = $this->buildStandardPageView();
|
||||
|
||||
$page->setApplicationName('Chat Log');
|
||||
$page->setBaseURI('/chatlog/');
|
||||
$page->setTitle(idx($data, 'title'));
|
||||
$page->setGlyph('#');
|
||||
$page->appendChild($view);
|
||||
|
||||
$response = new AphrontWebpageResponse();
|
||||
return $response->setContent($page->render());
|
||||
}
|
||||
|
||||
}
|
15
src/applications/chatlog/controller/base/__init__.php
Normal file
15
src/applications/chatlog/controller/base/__init__.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/webpage');
|
||||
phutil_require_module('phabricator', 'applications/base/controller/base');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorChatLogController.php');
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorChatLogChannelListController
|
||||
extends PhabricatorChatLogController {
|
||||
|
||||
public function processRequest() {
|
||||
|
||||
$table = new PhabricatorChatLogEvent();
|
||||
|
||||
$channels = queryfx_all(
|
||||
$table->establishConnection('r'),
|
||||
'SELECT DISTINCT channel FROM %T',
|
||||
$table->getTableName());
|
||||
|
||||
$rows = array();
|
||||
foreach ($channels as $channel) {
|
||||
$name = $channel['channel'];
|
||||
$rows[] = array(
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/chatlog/channel/'.phutil_escape_uri($name).'/',
|
||||
),
|
||||
phutil_escape_html($name)));
|
||||
}
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setHeaders(
|
||||
array(
|
||||
'Channel',
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
'pri wide',
|
||||
));
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->appendChild($table);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$panel,
|
||||
array(
|
||||
'title' => 'Channel List',
|
||||
));
|
||||
}
|
||||
}
|
18
src/applications/chatlog/controller/channellist/__init__.php
Normal file
18
src/applications/chatlog/controller/channellist/__init__.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/chatlog/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/chatlog/storage/event');
|
||||
phutil_require_module('phabricator', 'storage/queryfx');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorChatLogChannelListController.php');
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorChatLogChannelLogController
|
||||
extends PhabricatorChatLogController {
|
||||
|
||||
private $channel;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->channel = $data['channel'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$query = new PhabricatorChatLogQuery();
|
||||
$query->withChannels(array($this->channel));
|
||||
$query->setLimit(1000);
|
||||
$logs = $query->execute();
|
||||
|
||||
require_celerity_resource('phabricator-chatlog-css');
|
||||
|
||||
$last_author = null;
|
||||
$last_epoch = null;
|
||||
|
||||
$row_idx = 0;
|
||||
$row_colors = array(
|
||||
'normal',
|
||||
'alternate',
|
||||
);
|
||||
|
||||
$out = array();
|
||||
$out[] = '<table class="phabricator-chat-log">';
|
||||
foreach ($logs as $log) {
|
||||
$this_author = $log->getAuthor();
|
||||
$this_epoch = $log->getEpoch();
|
||||
|
||||
if (($this_author !== $last_author) ||
|
||||
($this_epoch - (60 * 5) > $last_epoch)) {
|
||||
++$row_idx;
|
||||
$out[] = '<tr class="initial '.$row_colors[$row_idx % 2].'">';
|
||||
$out[] = '<td class="timestamp">'.
|
||||
phabricator_datetime($log->getEpoch(), $user).'</td>';
|
||||
|
||||
$author = $log->getAuthor();
|
||||
$author = phutil_utf8_shorten($author, 18);
|
||||
$out[] = '<td class="author">'.
|
||||
phutil_escape_html($author).'</td>';
|
||||
} else {
|
||||
$out[] = '<tr class="'.$row_colors[$row_idx % 2].'">';
|
||||
$out[] = '<td class="similar" colspan="2"></td>';
|
||||
}
|
||||
$out[] = '<td class="message">'.
|
||||
phutil_escape_html($log->getMessage()).'</td>';
|
||||
$out[] = '</tr>';
|
||||
|
||||
$last_author = $this_author;
|
||||
$last_epoch = $this_epoch;
|
||||
}
|
||||
$out[] = '</table>';
|
||||
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
implode("\n", $out),
|
||||
array(
|
||||
'title' => 'Channel Log',
|
||||
));
|
||||
}
|
||||
}
|
18
src/applications/chatlog/controller/channellog/__init__.php
Normal file
18
src/applications/chatlog/controller/channellog/__init__.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/chatlog/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/chatlog/query');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/utils');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorChatLogChannelLogController.php');
|
80
src/applications/chatlog/query/PhabricatorChatLogQuery.php
Normal file
80
src/applications/chatlog/query/PhabricatorChatLogQuery.php
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorChatLogQuery {
|
||||
|
||||
private $channels;
|
||||
|
||||
private $limit;
|
||||
|
||||
public function withChannels(array $channels) {
|
||||
$this->channels = $channels;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setLimit($limit) {
|
||||
$this->limit = $limit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
$table = new PhabricatorChatLogEvent();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$where_clause = $this->buildWhereClause($conn_r);
|
||||
|
||||
$limit_clause = '';
|
||||
if ($this->limit) {
|
||||
$limit_clause = qsprintf(
|
||||
$conn_r,
|
||||
'LIMIT %d',
|
||||
$this->limit);
|
||||
}
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT * FROM %T e %Q ORDER BY epoch ASC %Q',
|
||||
$table->getTableName(),
|
||||
$where_clause,
|
||||
$limit_clause);
|
||||
|
||||
$logs = $table->loadAllFromArray($data);
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
private function buildWhereClause($conn_r) {
|
||||
$where = array();
|
||||
|
||||
if ($this->channels) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'channel IN (%Ls)',
|
||||
$this->channels);
|
||||
}
|
||||
|
||||
if ($where) {
|
||||
$where = 'WHERE ('.implode(') AND (', $where).')';
|
||||
} else {
|
||||
$where = '';
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
}
|
14
src/applications/chatlog/query/__init__.php
Normal file
14
src/applications/chatlog/query/__init__.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/chatlog/storage/event');
|
||||
phutil_require_module('phabricator', 'storage/qsprintf');
|
||||
phutil_require_module('phabricator', 'storage/queryfx');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorChatLogQuery.php');
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
abstract class PhabricatorChatLogDAO extends PhabricatorLiskDAO {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'chatlog';
|
||||
}
|
||||
|
||||
}
|
12
src/applications/chatlog/storage/base/__init__.php
Normal file
12
src/applications/chatlog/storage/base/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/base/storage/lisk');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorChatLogDAO.php');
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorChatLogEvent extends PhabricatorChatLogDAO {
|
||||
|
||||
protected $channel;
|
||||
protected $epoch;
|
||||
protected $author;
|
||||
protected $type;
|
||||
protected $message;
|
||||
protected $loggedByPHID;
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_TIMESTAMPS => false,
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
}
|
12
src/applications/chatlog/storage/event/__init__.php
Normal file
12
src/applications/chatlog/storage/event/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/chatlog/storage/base');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorChatLogEvent.php');
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
abstract class ConduitAPI_chatlog_Method extends ConduitAPIMethod {
|
||||
|
||||
}
|
12
src/applications/conduit/method/chatlog/base/__init__.php
Normal file
12
src/applications/conduit/method/chatlog/base/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
||||
|
||||
|
||||
phutil_require_source('ConduitAPI_chatlog_Method.php');
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
final class ConduitAPI_chatlog_query_Method
|
||||
extends ConduitAPI_chatlog_Method {
|
||||
|
||||
public function getMethodDescription() {
|
||||
return "(Unstable!) Retrieve chatter.";
|
||||
}
|
||||
|
||||
public function defineParamTypes() {
|
||||
return array(
|
||||
'channels' => 'optional list<string>',
|
||||
'limit' => 'optional int (default = 100)',
|
||||
);
|
||||
}
|
||||
|
||||
public function defineReturnType() {
|
||||
return 'nonempty list<dict>';
|
||||
}
|
||||
|
||||
public function defineErrorTypes() {
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function execute(ConduitAPIRequest $request) {
|
||||
|
||||
$query = new PhabricatorChatLogQuery();
|
||||
|
||||
$channels = $request->getValue('channels');
|
||||
if ($channels) {
|
||||
$query->withChannels($channels);
|
||||
}
|
||||
|
||||
$limit = $request->getValue('limit');
|
||||
if (!$limit) {
|
||||
$limit = 100;
|
||||
}
|
||||
$query->setLimit($limit);
|
||||
|
||||
$logs = $query->execute();
|
||||
|
||||
$results = array();
|
||||
foreach ($logs as $log) {
|
||||
$results[] = array(
|
||||
'channel' => $log->getChannel(),
|
||||
'epoch' => $log->getEpoch(),
|
||||
'author' => $log->getAuthor(),
|
||||
'type' => $log->getType(),
|
||||
'message' => $log->getMessage(),
|
||||
'loggedByPHID' => $log->getLoggedByPHID(),
|
||||
);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
13
src/applications/conduit/method/chatlog/query/__init__.php
Normal file
13
src/applications/conduit/method/chatlog/query/__init__.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/chatlog/query');
|
||||
phutil_require_module('phabricator', 'applications/conduit/method/chatlog/base');
|
||||
|
||||
|
||||
phutil_require_source('ConduitAPI_chatlog_query_Method.php');
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
final class ConduitAPI_chatlog_record_Method
|
||||
extends ConduitAPI_chatlog_Method {
|
||||
|
||||
public function getMethodDescription() {
|
||||
return "(Unstable!) Record chatter.";
|
||||
}
|
||||
|
||||
public function defineParamTypes() {
|
||||
return array(
|
||||
'logs' => 'required list<dict>',
|
||||
);
|
||||
}
|
||||
|
||||
public function defineReturnType() {
|
||||
return 'list<id>';
|
||||
}
|
||||
|
||||
public function defineErrorTypes() {
|
||||
return array(
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(ConduitAPIRequest $request) {
|
||||
$logs = $request->getValue('logs');
|
||||
if (!is_array($logs)) {
|
||||
$logs = array();
|
||||
}
|
||||
|
||||
$template = new PhabricatorChatLogEvent();
|
||||
$template->setLoggedByPHID($request->getUser()->getPHID());
|
||||
|
||||
$objs = array();
|
||||
foreach ($logs as $log) {
|
||||
$obj = clone $template;
|
||||
$obj->setChannel(idx($log, 'channel'));
|
||||
$obj->setType(idx($log, 'type'));
|
||||
$obj->setAuthor(idx($log, 'author'));
|
||||
$obj->setEpoch(idx($log, 'epoch'));
|
||||
$obj->setMessage(idx($log, 'message'));
|
||||
$obj->save();
|
||||
|
||||
$objs[] = $obj;
|
||||
}
|
||||
|
||||
return array_values(mpull($objs, 'getID'));
|
||||
}
|
||||
|
||||
}
|
15
src/applications/conduit/method/chatlog/record/__init__.php
Normal file
15
src/applications/conduit/method/chatlog/record/__init__.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/chatlog/storage/event');
|
||||
phutil_require_module('phabricator', 'applications/conduit/method/chatlog/base');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('ConduitAPI_chatlog_record_Method.php');
|
|
@ -50,6 +50,8 @@ the IRC bot. These are the default handlers available:
|
|||
- @{class:PhabricatorIRCDifferentialNotificationHandler} This handler posts
|
||||
notifications about changes to revisions to IRC to the channels listed in
|
||||
##notification.channels##.
|
||||
- @{class:PhabricatorIRCLogHandler} This handler records chatlogs which can
|
||||
be browsed in the Phabricator web interface.
|
||||
|
||||
You can also write your own handlers, by extending
|
||||
@{class:PhabricatorIRCHandler}.
|
||||
|
|
|
@ -44,7 +44,9 @@ abstract class PhabricatorIRCHandler {
|
|||
}
|
||||
|
||||
final protected function getURI($path) {
|
||||
return $this->bot->getConfig('conduit.uri').$path;
|
||||
$base_uri = new PhutilURI($this->bot->getConfig('conduit.uri'));
|
||||
$base_uri->setPath($path);
|
||||
return (string)$base_uri;
|
||||
}
|
||||
|
||||
final protected function isChannelName($name) {
|
||||
|
|
|
@ -6,5 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phutil', 'parser/uri');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorIRCHandler.php');
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Looks for Dxxxx, Txxxx and links to them.
|
||||
*
|
||||
* @group irc
|
||||
*/
|
||||
final class PhabricatorIRCLogHandler extends PhabricatorIRCHandler {
|
||||
|
||||
private $futures = array();
|
||||
|
||||
public function receiveMessage(PhabricatorIRCMessage $message) {
|
||||
|
||||
switch ($message->getCommand()) {
|
||||
case 'PRIVMSG':
|
||||
$reply_to = $message->getReplyTo();
|
||||
if (!$reply_to) {
|
||||
break;
|
||||
}
|
||||
if (!$this->isChannelName($reply_to)) {
|
||||
// Don't log private messages, although maybe we should for debugging?
|
||||
break;
|
||||
}
|
||||
|
||||
$logs = array(
|
||||
array(
|
||||
'channel' => $reply_to,
|
||||
'type' => 'mesg',
|
||||
'epoch' => time(),
|
||||
'author' => $message->getSenderNickname(),
|
||||
'message' => $message->getMessageText(),
|
||||
),
|
||||
);
|
||||
|
||||
$this->futures[] = $this->getConduit()->callMethod(
|
||||
'chatlog.record',
|
||||
array(
|
||||
'logs' => $logs,
|
||||
));
|
||||
|
||||
$prompts = array(
|
||||
'/where is the (chat)?log\?/i',
|
||||
'/where am i\?/i',
|
||||
'/what year is (this|it)\?/i',
|
||||
);
|
||||
|
||||
$tell = false;
|
||||
foreach ($prompts as $prompt) {
|
||||
if (preg_match($prompt, $message->getMessageText())) {
|
||||
$tell = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($tell) {
|
||||
$response = $this->getURI(
|
||||
'/chatlog/channel/'.phutil_escape_uri($reply_to).'/');
|
||||
$this->write('PRIVMSG', "{$reply_to} :{$response}");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function runBackgroundTasks() {
|
||||
foreach ($this->futures as $key => $future) {
|
||||
try {
|
||||
if ($future->isReady()) {
|
||||
unset($this->futures[$key]);
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
unset($this->futures[$key]);
|
||||
phlog($ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
15
src/infrastructure/daemon/irc/handler/log/__init__.php
Normal file
15
src/infrastructure/daemon/irc/handler/log/__init__.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infrastructure/daemon/irc/handler/base');
|
||||
|
||||
phutil_require_module('phutil', 'error');
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorIRCLogHandler.php');
|
|
@ -57,6 +57,13 @@ final class PhabricatorIRCMessage {
|
|||
return null;
|
||||
}
|
||||
|
||||
public function getSenderNickname() {
|
||||
$nick = $this->getRawSender();
|
||||
$nick = ltrim($nick, ':');
|
||||
$nick = head(explode('!', $nick));
|
||||
return $nick;
|
||||
}
|
||||
|
||||
public function getTarget() {
|
||||
switch ($this->getCommand()) {
|
||||
case 'PRIVMSG':
|
||||
|
|
|
@ -6,5 +6,7 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorIRCMessage.php');
|
||||
|
|
39
webroot/rsrc/css/application/chatlog/chatlog.css
Normal file
39
webroot/rsrc/css/application/chatlog/chatlog.css
Normal file
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* @provides phabricator-chatlog-css
|
||||
*/
|
||||
|
||||
.phabricator-chat-log {
|
||||
margin: 1em 2em;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.phabricator-chat-log tr.initial {
|
||||
border-top: 4px solid white;
|
||||
}
|
||||
|
||||
.phabricator-chat-log tr.normal {
|
||||
background: #e9e9e9;
|
||||
}
|
||||
|
||||
.phabricator-chat-log tr.alternate {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
|
||||
.phabricator-chat-log td {
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.phabricator-chat-log td.timestamp {
|
||||
white-space: nowrap;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.phabricator-chat-log td.author {
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.phabricator-chat-log td.message {
|
||||
width: 100%;
|
||||
}
|
Loading…
Reference in a new issue