plugin.py 4.49 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# This file is part of Birthday Reminder.
#
# Birthday Reminder 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; version 3 only.
#
# Birthday Reminder 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Birthday Reminder.  If not, see <http://www.gnu.org/licenses/>.

15
import os
Philipp Hörist's avatar
Philipp Hörist committed
16
import json
17
import datetime
Philipp Hörist's avatar
Philipp Hörist committed
18 19 20
import logging

from gi.repository import GLib
21

22 23 24
from gajim.common import configpaths
from gajim.common import app
from gajim.common import ged
25

26 27 28
from gajim.plugins import GajimPlugin
from gajim.plugins.plugins_i18n import _

29

Philipp Hörist's avatar
Philipp Hörist committed
30
log = logging.getLogger('gajim.p.birthday')
31

Philipp Hörist's avatar
Philipp Hörist committed
32 33
TITLE = _('%s has birthday today')
TEXT = _('Send him a message')
34 35


Philipp Hörist's avatar
Philipp Hörist committed
36 37
class BirthDayPlugin(GajimPlugin):
    def init(self):
38 39
        self.config_dialog = None
        self.description = ('Birthday reminder plugin')
40
        self.events_handlers = {
Philipp Hörist's avatar
Philipp Hörist committed
41
            'vcard-received': (ged.GUI2, self._vcard_received)}
42

43
        self._timeout_id = None
Philipp Hörist's avatar
Philipp Hörist committed
44
        self._timeout_id_start = None
45

Philipp Hörist's avatar
Philipp Hörist committed
46
        self.showed_accounts = []
47

Philipp Hörist's avatar
Philipp Hörist committed
48 49
        self._birthdays = {}
        self._load_birthdays()
50

Philipp Hörist's avatar
Philipp Hörist committed
51 52 53 54 55
    def activate(self):
        self._timeout_id_start = GLib.timeout_add_seconds(
            5, self._check_birthdays_at_start)
        self._timeout_id = GLib.timeout_add_seconds(
            86400, self._check_birthdays)
56

Philipp Hörist's avatar
Philipp Hörist committed
57 58
    def deactivate(self):
        if self._timeout_id is not None:
59
            GLib.source_remove(self._timeout_id)
Philipp Hörist's avatar
Philipp Hörist committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
        if self._timeout_id_start is not None:
            GLib.source_remove(self._timeout_id_start)

    def _load_birthdays(self):
        path = os.path.join(configpaths.get('MY_DATA'), 'birthdays.json')
        if os.path.exists(path):
            with open(path, 'r', encoding='utf-8') as file:
                content = file.read()
                if content:
                    self._birthdays = json.loads(content)

    def _store_birthdays(self):
        path = os.path.join(configpaths.get('MY_DATA'), 'birthdays.json')
        with open(path, 'w', encoding='utf-8') as file:
            json.dump(self._birthdays, file)

    def _vcard_received(self, event):
        birthday = event.vcard_dict.get('BDAY')
        if not birthday:
            if event.jid in self._birthdays:
                del self._birthdays[event.jid]
                log.info('Received empty birthday: %s', event.jid)
        else:
83
            try:
Philipp Hörist's avatar
Philipp Hörist committed
84 85 86 87 88 89 90 91
                year, month, day = birthday.split('-')
                year = int(year)
                month = int(month)
                day = int(day)
            except Exception:
                log.warning('Invalid date: %s', birthday)
                if event.jid in self._birthdays:
                    del self._birthdays[event.jid]
92
            else:
Philipp Hörist's avatar
Philipp Hörist committed
93 94 95 96
                self._birthdays[event.jid] = (year, month, day)
                log.info('Received birthday: %s %s',
                         event.jid, (year, month, day))
        self._store_birthdays()
97

Philipp Hörist's avatar
Philipp Hörist committed
98 99
    def _check_birthdays_at_start(self):
        self._check_birthdays()
100

Philipp Hörist's avatar
Philipp Hörist committed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
    def _check_birthdays(self):
        log.info('Check birthdays...')
        today = datetime.date.today()
        for jid, birthdate in self._birthdays.items():
            year, month, day = birthdate
            if today.month == month and today.day == day:
                account, contact = self._find_contact(jid)
                if contact is None:
                    if jid in self._birthdays:
                        del self._birthdays[jid]
                        self._store_birthdays()
                        continue
                else:
                    log.info('Issue notification for %s', jid)
                    nick = contact.get_shown_name() or jid
                    app.notification.popup(
                        'reminder',
                        jid,
                        account,
                        icon_name='trophy-gold',
                        title=TITLE % GLib.markup_escape_text(nick),
                        text=TEXT)
123

Philipp Hörist's avatar
Philipp Hörist committed
124
        return True
125

126 127
    @staticmethod
    def _find_contact(jid):
Philipp Hörist's avatar
Philipp Hörist committed
128 129 130 131 132
        accounts = app.contacts.get_accounts()
        for account in accounts:
            contact = app.contacts.get_contacts(account, jid)
            if contact is not None:
                return account, contact[0]