Skip to content

Commit

Permalink
Add classifier for new messages
Browse files Browse the repository at this point in the history
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
  • Loading branch information
ChristophWurst committed Apr 23, 2020
1 parent e8772da commit 74d5c73
Show file tree
Hide file tree
Showing 19 changed files with 403 additions and 18 deletions.
3 changes: 0 additions & 3 deletions css/mail.scss
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,6 @@
.icon-drafts {
@include icon-color('drafts', 'mail', $color-black);
}
.icon-important {
@include icon-color('important', 'mail', $color-black);
}
.icon-sent {
@include icon-color('sent', 'mail', $color-black);
}
Expand Down
2 changes: 1 addition & 1 deletion img/important.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions lib/AppInfo/BootstrapSingleton.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use OCA\Mail\Events\MessageDeletedEvent;
use OCA\Mail\Events\MessageFlaggedEvent;
use OCA\Mail\Events\MessageSentEvent;
use OCA\Mail\Events\NewMessagesSynchronized;
use OCA\Mail\Events\SaveDraftEvent;
use OCA\Mail\Http\Middleware\ErrorMiddleware;
use OCA\Mail\Http\Middleware\ProvisioningMiddleware;
Expand All @@ -45,6 +46,7 @@
use OCA\Mail\Listener\FlagRepliedMessageListener;
use OCA\Mail\Listener\InteractionListener;
use OCA\Mail\Listener\MessageCacheUpdaterListener;
use OCA\Mail\Listener\NewMessageClassificationListener;
use OCA\Mail\Listener\SaveSentMessageListener;
use OCA\Mail\Listener\TrashMailboxCreatorListener;
use OCA\Mail\Service\Attachment\AttachmentService;
Expand Down Expand Up @@ -135,6 +137,7 @@ private function registerEvents(IAppContainer $container): void {
$dispatcher->addServiceListener(MessageSentEvent::class, FlagRepliedMessageListener::class);
$dispatcher->addServiceListener(MessageSentEvent::class, InteractionListener::class);
$dispatcher->addServiceListener(MessageSentEvent::class, SaveSentMessageListener::class);
$dispatcher->addServiceListener(NewMessagesSynchronized::class, NewMessageClassificationListener::class);
$dispatcher->addServiceListener(SaveDraftEvent::class, DraftMailboxCreatorListener::class);
}
}
2 changes: 1 addition & 1 deletion lib/Db/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class Message extends Entity implements JsonSerializable {
protected $updatedAt;
protected $structureAnalyzed;
protected $flagAttachments;
protected $flagImportant;
protected $flagImportant = false;
protected $previewText;

/** @var AddressList */
Expand Down
2 changes: 2 additions & 0 deletions lib/Db/MessageMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ public function insertBulk(Message ...$messages): void {
$qb1->setValue('flag_forwarded', $qb1->createParameter('flag_forwarded'));
$qb1->setValue('flag_junk', $qb1->createParameter('flag_junk'));
$qb1->setValue('flag_notjunk', $qb1->createParameter('flag_notjunk'));
$qb1->setValue('flag_important', $qb1->createParameter('flag_important'));
$qb2 = $this->db->getQueryBuilder();

$qb2->insert('mail_recipients')
Expand All @@ -126,6 +127,7 @@ public function insertBulk(Message ...$messages): void {
$qb1->setParameter('flag_forwarded', $message->getFlagForwarded(), IQueryBuilder::PARAM_BOOL);
$qb1->setParameter('flag_junk', $message->getFlagJunk(), IQueryBuilder::PARAM_BOOL);
$qb1->setParameter('flag_notjunk', $message->getFlagNotjunk(), IQueryBuilder::PARAM_BOOL);
$qb1->setParameter('flag_important', $message->getFlagImportant(), IQueryBuilder::PARAM_BOOL);

$qb1->execute();

Expand Down
72 changes: 72 additions & 0 deletions lib/Events/NewMessagesSynchronized.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

namespace OCA\Mail\Events;

use OCA\Mail\Account;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\Message;
use OCP\EventDispatcher\Event;

class NewMessagesSynchronized extends Event {

/** @var Account */
private $account;

/** @var Mailbox */
private $mailbox;

/** @var array|Message[] */
private $messages;

/**
* @param Account $account
* @param Mailbox $mailbox
* @param Message[] $messages
*/
public function __construct(Account $account,
Mailbox $mailbox,
array $messages) {
parent::__construct();
$this->account = $account;
$this->mailbox = $mailbox;
$this->messages = $messages;
}

public function getAccount(): Account {
return $this->account;
}

public function getMailbox(): Mailbox {
return $this->mailbox;
}

/**
* @return Message[]
*/
public function getMessages() {
return $this->messages;
}
}
53 changes: 53 additions & 0 deletions lib/Listener/NewMessageClassificationListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

namespace OCA\Mail\Listener;

use OCA\Mail\Events\NewMessagesSynchronized;
use OCA\Mail\Service\Classification\MessageClassifier;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;

class NewMessageClassificationListener implements IEventListener {

/** @var MessageClassifier */
private $classifier;

public function __construct(MessageClassifier $classifier) {
$this->classifier = $classifier;
}

public function handle(Event $event): void {
if (!($event instanceof NewMessagesSynchronized)) {
return;
}

foreach ($event->getMessages() as $message) {
if ($this->classifier->isImportant($event->getAccount(), $event->getMailbox(), $message)) {
$message->setFlagImportant(true);
}
}
}
}
1 change: 0 additions & 1 deletion lib/Migration/Version1040Date20200422130220.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,4 @@ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array
$deleteRecipients = $qb2->delete('mail_recipients');
$deleteRecipients->execute();
}

}
1 change: 0 additions & 1 deletion lib/Migration/Version1040Date20200422142920.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,4 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt

return $schema;
}

}
53 changes: 53 additions & 0 deletions lib/Service/Classification/AClassifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

namespace OCA\Mail\Service\Classification;

use OCA\Mail\Account;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\Message;

abstract class AClassifier {
abstract public function isImportant(Account $account, Mailbox $mailbox, Message $message): bool;

final public function or(AClassifier $next): AClassifier {
return new class($this, $next) extends AClassifier {
/** @var AClassifier */
private $outer;

/** @var AClassifier */
private $next;

public function __construct(AClassifier $outer, AClassifier $next) {
$this->outer = $outer;
$this->next = $next;
}

public function isImportant(Account $account, Mailbox $mailbox, Message $message): bool {
return $this->outer->isImportant($account, $mailbox, $message) || $this->next->isImportant($account, $mailbox, $message);
}
};
}
}
65 changes: 65 additions & 0 deletions lib/Service/Classification/MessageClassifier.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

namespace OCA\Mail\Service\Classification;

use OCA\Mail\Account;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\Message;

class MessageClassifier {

/** @var AClassifier */
private $oftenImportantSenderClassifier;

/** @var AClassifier */
private $oftenContactedSenderClassifier;

/** @var AClassifier */
private $oftenReadSenderClassifier;

/** @var AClassifier */
private $oftenRepliedSenderClassifier;

public function __construct(OftenImportantSenderClassifier $oftenImportantSenderClassifier,
OftenContactedSenderClassifier $oftenContactedSenderClassifier,
OftenReadSenderClassifier $oftenReadSenderClassifier,
OftenRepliedSenderClassifier $oftenRepliedSenderClassifier) {
$this->oftenImportantSenderClassifier = $oftenImportantSenderClassifier;
$this->oftenContactedSenderClassifier = $oftenContactedSenderClassifier;
$this->oftenReadSenderClassifier = $oftenReadSenderClassifier;
$this->oftenRepliedSenderClassifier = $oftenRepliedSenderClassifier;
}

public function isImportant(Account $account,
Mailbox $mailbox,
Message $message): bool {
return $this->oftenImportantSenderClassifier
->or($this->oftenContactedSenderClassifier)
->or($this->oftenReadSenderClassifier)
->or($this->oftenRepliedSenderClassifier)
->isImportant($account, $mailbox, $message);
}
}
4 changes: 2 additions & 2 deletions lib/Service/Classification/OftenContactedSenderClassifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ private function getMessagesSentTotal(Mailbox $mb): int {

$select = $qb->select($qb->func()->count('*'))
->from('mail_recipients', 'r')
->join('r', 'mail_messages', 'm', $qb->expr()->eq('m.id', 'r.message_id', IQueryBuilder::PARAM_INT))
->join('r', 'mail_mailboxes', 'mb', $qb->expr()->eq('mb.id', $qb->expr()->castColumn('m.mailbox_id', IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT))
->join('r', 'mail_messages', 'm', $qb->expr()->eq('m.id', 'r.message_id'))
->join('r', 'mail_mailboxes', 'mb', $qb->expr()->eq('mb.id', 'm.mailbox_id'))
->where($qb->expr()->eq('r.id', $qb->createNamedParameter(Address::TYPE_FROM), IQueryBuilder::PARAM_INT))
->andWhere($qb->expr()->eq('mb.id', $qb->createNamedParameter($mb->getId(), IQueryBuilder::PARAM_INT)));
$result = $select->execute();
Expand Down
38 changes: 38 additions & 0 deletions lib/Service/Classification/SafeRatio.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

namespace OCA\Mail\Service\Classification;

trait SafeRatio {
protected function greater(int $num,
int $of,
float $threshold,
bool $default = false): bool {
if ($of === 0) {
return $default;
}
return $num / $of > $threshold;
}
}
Loading

0 comments on commit 74d5c73

Please sign in to comment.