Skip to content
Snippets Groups Projects
Commit 5d052ab7 authored by Thomas Hackl's avatar Thomas Hackl
Browse files

process news posting to Matrix via cronjob so that news are pushed when their...

process news posting to Matrix via cronjob so that news are pushed when their publish date is reached and not immediately
parent f9e6b61c
No related branches found
No related tags found
No related merge requests found
...@@ -32,8 +32,8 @@ class MatrixPlugin extends StudIPPlugin implements StandardPlugin ...@@ -32,8 +32,8 @@ class MatrixPlugin extends StudIPPlugin implements StandardPlugin
NotificationCenter::addObserver($this, 'uninvite', 'CourseMemberDidDelete'); NotificationCenter::addObserver($this, 'uninvite', 'CourseMemberDidDelete');
NotificationCenter::addObserver($this, 'unregister', 'UserDidDelete'); NotificationCenter::addObserver($this, 'unregister', 'UserDidDelete');
NotificationCenter::addObserver($this, 'deleteRoom', 'CourseDidDelete'); NotificationCenter::addObserver($this, 'deleteRoom', 'CourseDidDelete');
NotificationCenter::addObserver($this, 'postNews', 'StudipNewsDidCreate'); NotificationCenter::addObserver($this, 'updateCronjob', 'StudipNewsWillUpdate');
NotificationCenter::addObserver($this, 'postNews', 'StudipNewsDidUpdate'); NotificationCenter::addObserver($this, 'updateCronjob', 'StudipNewsDidDelete');
$this->addScript('assets/javascripts/matrixchat.js'); $this->addScript('assets/javascripts/matrixchat.js');
$this->addStylesheet('assets/stylesheets/matrixchat.scss'); $this->addStylesheet('assets/stylesheets/matrixchat.scss');
...@@ -94,6 +94,7 @@ class MatrixPlugin extends StudIPPlugin implements StandardPlugin ...@@ -94,6 +94,7 @@ class MatrixPlugin extends StudIPPlugin implements StandardPlugin
public function getMetadata() public function getMetadata()
{ {
return [ return [
'pluginname' => dgettext('matrix', 'Matrix-Chat'),
'summary' => dgettext('matrix', 'Chat via Matrix'), 'summary' => dgettext('matrix', 'Chat via Matrix'),
'description' => dgettext('matrix', 'Matrix-Chaträume für Veranstaltungen'), 'description' => dgettext('matrix', 'Matrix-Chaträume für Veranstaltungen'),
'category' => _('Kommunikation und Zusammenarbeit'), 'category' => _('Kommunikation und Zusammenarbeit'),
...@@ -194,22 +195,28 @@ class MatrixPlugin extends StudIPPlugin implements StandardPlugin ...@@ -194,22 +195,28 @@ class MatrixPlugin extends StudIPPlugin implements StandardPlugin
} }
/** /**
* Auto-post course news to associated Matrix room if configured. * Remove news from entries relevant for cronjob.
* *
* @param string $event * @param string $event
* @param StudipNews $news * @param StudipNews $news
*/ */
public function postNews($event, $news) public function updateCronjob($event, $news)
{ {
foreach ($news->news_ranges as $range) { switch ($event) {
if ($range->course && MatrixRoom::hasRoom($range->course->id)) { case 'StudipNewsWillUpdate':
MatrixClient::get()->postMessage( if ($news->isFieldDirty('date')) {
MatrixAccount::requireSystemAccount(), DBManager::get()->execute(
MatrixRoom::find($range->course->id)->getLinkedRoom(), "UPDATE `matrix_upcoming_news` SET `publish_at` = :publish WHERE `news_id` = :id",
'Ankündigung: ' . $news->topic . '' . strip_tags($news->body), ['publish' => $news->date, 'id' => $news->id]
'<strong>Ankündigung: ' . $news->topic . '</strong><br>' . $news->body );
}
break;
case 'StudipNewsDidDelete':
DBManager::get()->execute(
"DELETE FROM `matrix_upcoming_news` WHERE `news_id` = :id",
['id' => $news->id]
); );
} break;
} }
} }
......
<?php
/**
* Class MatrixPostNewsCronjob
* Cronjob that checks if a course with attached Matrix chatroom has any news, registers them as "to do"
* and posts the news content when the news are published in Stud.IP. Publishing news happens at a date
* given per news entry, so this cannot be done "live" after the news has been created.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* @author Thomas Hackl <hackl@data-quest.de>
* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
* @category Matrix
*/
require_once(__DIR__ . '/vendor/libpatrix/MatrixClient.php');
class MatrixPostNewsCronjob extends CronJob
{
public static function getName()
{
return dgettext('matrix', 'Aktuelle Ankündigungen in Matrixraum veröffentlichen');
}
public static function getDescription()
{
return dgettext('matrix', 'Dieser Cronjob veröffentlicht eine Ankündigung im zugehörigen ' .
'Matrixraum, wenn sie auch in der entsprechenden Veranstaltung öffentlich wird.');
}
public static function getParameters()
{
return [
'verbose' => [
'type' => 'boolean',
'default' => false,
'status' => 'optional',
'description' => _('Sollen Ausgaben erzeugt werden'),
],
];
}
public function execute($last_result, $parameters = [])
{
/*
* First, check if there are news that need to be monitored until they are published.
* This means getting all news
* - that belong to a course with attaached Matrix room
* - that haven't expired
* - that haven't already been posted
* and inserting them into the monitoring table or updating them accordingly.
*/
DBManager::get()->execute("INSERT INTO `matrix_upcoming_news`
(
SELECT DISTINCT n.`news_id`, r.`range_id`, n.`date`, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP() FROM `news` n
JOIN `news_range` r USING (`news_id`)
JOIN `matrix_rooms` m ON (m.`range_id` = r.`range_id`)
WHERE UNIX_TIMESTAMP() <= n.`date` + n.`expire`
)
ON DUPLICATE KEY UPDATE `publish_at` = VALUES(`publish_at`), `chdate` = UNIX_TIMESTAMP()",
['now' => time()]
);
/*
* Now walk through entries in monitoring table and push each entry
* to the corresponding chatroom if publish_date is reached.
*/
$news = DBManager::get()->fetchFirst(
"SELECT `news_id` FROM `matrix_upcoming_news` WHERE `publish_at` <= UNIX_TIMESTAMP() AND `posted` = 0"
);
// Verbose output
if ($parameters['verbose']) {
echo "Got news_ids:\n";
print_r($news);
}
foreach (StudipNews::findMany($news) as $one) {
foreach ($one->news_ranges as $range) {
$success = false;
if ($range->course && MatrixRoom::hasRoom($range->course->id)) {
$room = MatrixRoom::find($range->course->id);
$success = MatrixClient::get()->postMessage(
MatrixAccount::requireSystemAccount(),
$room->getLinkedRoom(),
'Ankündigung: ' . $one->topic . ' ' . strip_tags($one->body),
'<strong>Ankündigung: ' . $one->topic . '</strong><br>' . $one->body
);
// Mark entry as done after message has been posted to Matrix room successfully.
if ($success) {
// Verbose output
if ($parameters['verbose']) {
echo sprintf(
"Posted news entry $1%s to Matrix room $2%s in course $3%s.\n",
$news->id, $room->matrix_room_id, $room->range_id
);
}
DBManager::get()->execute(
"UPDATE `matrix_upcoming_news` SET `posted` = 1 WHERE `news_id` = :id AND `range_id` = :range",
['id' => $one->id, 'range' => $range->course->id]
);
}
}
}
}
// Finally: cleanup news entries that are already expired and need not be considered anymore.
DBManager::get()->execute("DELETE FROM `matrix_upcoming_news` WHERE `news_id` IN (
SELECT DISTINCT n.`news_id` FROM `news` n
JOIN `matrix_upcoming_news` m USING (`news_id`)
WHERE n.`date` + n.`expire` < UNIX_TIMESTAMP()
)"
);
}
}
...@@ -79,8 +79,11 @@ class MatrixChatController extends AuthenticatedController ...@@ -79,8 +79,11 @@ class MatrixChatController extends AuthenticatedController
$this->hasToCreate = false; $this->hasToCreate = false;
if ($this->account) { if ($this->account) {
//$room->requireMembership($this->account->getLinkedAccount()); if (Config::get()->MATRIX_AUTO_CREATE_ACCOUNTS) {
$invited = $room->requireInvitation($this->account->getLinkedAccount()); $room->requireMembership($this->account->getLinkedAccount());
} else {
$invited = $room->requireInvitation($this->account->getLinkedAccount());
}
} }
} }
} }
......
<?php
/**
* Class PostNewsToMatrixCronjob
* Registers a cronjob for posting news at publish time
* to the corresponding Matrix chatroom.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* @author Thomas Hackl <hackl@data-quest.de>
* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
* @category Matrix
*/
require_once(__DIR__ . '/../MatrixPostNewsCronjob.php');
class PostNewsToMatrixCronjob extends Migration
{
public function description()
{
return 'Registers a cronjob for posting news at publish time to the corresponding Matrix chatroom.';
}
public function up()
{
/**
* Collect news entries that need to be published to a Matrix chatroom.
*/
DBManager::get()->execute("CREATE TABLE IF NOT EXISTS `matrix_upcoming_news` (
`news_id` CHAR(32) NOT NULL COLLATE latin1_bin,
`range_id` CHAR(32) NOT NULL COLLATE latin1_bin,
`publish_at` INT,
`posted` TINYINT(1) NOT NULL DEFAULT 0,
`mkdate` INT NOT NULL,
`chdate` INT NOT NULL,
PRIMARY KEY (`news_id`, `range_id`)
) ENGINE InnoDB ROW_FORMAT=DYNAMIC");
MatrixPostNewsCronjob::register()->schedulePeriodic(-15)->activate();
}
public function down()
{
MatrixPostNewsCronjob::unregister();
DBManager::get()->execute("DROP TABLE IF EXISTS `matrix_upcoming_news`");
}
}
\ No newline at end of file
...@@ -124,7 +124,7 @@ class MatrixRoom extends SimpleORMap ...@@ -124,7 +124,7 @@ class MatrixRoom extends SimpleORMap
public function getLinkedRoom() public function getLinkedRoom()
{ {
return new Patrix\Room($this->matrix_room_id, Context::getHeaderLine()); return new Patrix\Room($this->matrix_room_id, Context::get() ? Context::getHeaderLine() : '');
} }
public function requireMembership($account) public function requireMembership($account)
......
pluginname=Matrix-Chat pluginname=Matrix-Chat
pluginclassname=MatrixPlugin pluginclassname=MatrixPlugin
origin=data-quest origin=data-quest
version=1.2.1 version=1.3
screenshot=assets/images/matrix_logo.png screenshot=assets/images/matrix_logo.png
description=Matrix chat for Stud.IP courses description=Matrix chat for Stud.IP courses
studipMinVersion=4.5 studipMinVersion=4.5
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment