Ejemplo n.º 1
0
    def __init__(self):

        self.seenHunts = dict()
        self.mail = imaplib.IMAP4_SSL('imap.gmail.com')
        self.mail.login(settings.Settings().rpmail_username,
                        settings.Settings().rpmail_pass)
        self.mail.select('INBOX')
        self.bot = None
        self.botan = Botan(settings.Settings().botan_key)

        # sets met chat_ids die updates willen ontvangen.
        self._A = set()  # naam niet veranderen
        self._B = set()  # naam niet veranderen
        self._C = set()  # naam niet veranderen
        self._D = set()  # naam niet veranderen
        self._E = set()  # naam niet veranderen
        self._F = set()  # naam niet veranderen
        self._X = set()  # naam niet veranderen
        self._photos = set()  # naam niet veranderen
        self._opdrachten = set()  # naam niet veranderen
        self._nieuws = set()  # naam niet veranderen
        self._error = set()  # naam niet veranderen
        self._hints = set()  # naam niet veranderen
        self._punten = {'opdrachten': 0,
                        'hints': 0,
                        'hunts': 0,
                        'fotos': 0,
                        'totaal': 0}

        self._last_update = 0
        self.lastA = None
        self.lastB = None
        self.lastC = None
        self.lastD = None
        self.lastE = None
        self.lastF = None
        self.lastX = None
        self.lastPhoto = None
        self.lastOpdracht = None
        self.lastNieuws = None
        self.lastStatus = None
        self.seenMail = set()
        self.lastHint = None
        self.rp_api = RPApi.get_instance(settings.Settings().rp_username,
                                         settings.Settings().rp_pass)
Ejemplo n.º 2
0
    def __init__(self):
        self._reminders_lock = threading.Lock()
        self.mail = imaplib.IMAP4_SSL('imap.gmail.com')
        self.seenHunts = dict()
        self.bot = None
        self.botan = Botan(settings.Settings().botan_key)
        self.rp_api = RPApi.get_instance(settings.Settings().rp_username,
                                         settings.Settings().rp_pass)
        self.messages = []  # list of tuples (int, str, str, tuple, dict)

        def get_kwargs_vos(new_item):
            if new_item['icon'] == '3':
                new_item['soort'] = 'Spot'
            elif new_item['icon'] == '4':
                new_item['soort'] = 'Hunt'
            else:
                new_item['soort'] = 'Hint'
            new_item['team_upper'] = new_item['team'].upper()
            new_item['tijd'] = new_item['datetime'][11:]
            return new_item.data

        def get_kwargs_vos_status(new_item):
            new_item['dg'] = new_item['team'][0].lower()
            return new_item._data

        def send_location(vos, chat_ids):
            bot = get_updates().bot
            if bot is not None:
                for chat_id in chat_ids:
                    bot.sendLocation(chat_id, latitude=vos['latitude'],
                                     longitude=vos['longitude'])

        def send_status_sticker(status, chat_ids):
            bot = get_updates().bot
            vos = status['dg']
            new_status = status['status']
            if bot is not None:
                for chat_id in chat_ids:
                    bot.sendSticker(chat_id,
                                    status_plaatjes[vos][new_status]['file_id']
                                    )
            send_cloudmessage(vos, new_status)

        message_vos = 'er is een {soort} ingevoerd voor {team}.\n' \
                      ' extra info: {extra}\n ' \
                      'opmerking/adres: {opmerking}\n' \
                      'tijd: {tijd}\n' \
                      'link: http://jotihunt2016.area348.nl/map.php?gebied=' \
                      '{team_upper}'
        message_vos_status = 'Er is een nieuwe status voor {team}'
        self.botan_id_vos = 'newLoc_{team}_{soort}'
        self.botan_id_vos_status = 'newStatus_{dg}_{status}'

        def get_retriever(dg):
            def retriever():
                return self.rp_api.vos(dg)
            return retriever

        def get_retriever_status(dg):
            def retriever():
                return jotihuntApi.get_vossen().data[dg]
            return retriever

        for dg in ['a', 'b', 'c', 'd', 'e', 'f', 'x']:
            retr1 = get_retriever(dg)
            updater_rp = SingleUpdater(retr1,
                                       get_kwargs_vos, message_vos,
                                       botan_id=self.botan_id_vos+'_'+dg,
                                       callback=send_location)
            retr = get_retriever_status(dg)
            updater_status = SingleUpdater(retr, get_kwargs_vos_status,
                                           message_vos_status,
                                           botan_id=self.botan_id_vos_status
                                           + '_'+dg,
                                           callback=send_status_sticker)
            if dg == 'a':
                self._A = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'b':
                self._B = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'c':
                self._C = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'd':
                self._D = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'e':
                self._E = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'f':
                self._F = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'x':
                self._X = SingleUpdateContainer([updater_rp, updater_status])

        self._photos = set()  # naam niet veranderen
        get_last_opdracht = lambda: jotihuntApi.get_opdrachten().data[0]
        get_last_nieuws = lambda: jotihuntApi.get_nieuws_lijst().data[0]
        get_last_hint = lambda: jotihuntApi.get_hints().data[0]
        self.botan_id_jotihunt = 'new_{botan_soort}'

        def get_jotihunt_kwargs(new_response):
            r = dict()
            item = new_response.data
            r['title'] = item.titel
            if isinstance(item, jotihuntApiBase.Opdracht):
                r['url'] = settings.Settings().base_opdracht_url + item.ID
                r['soort'] = 'een nieuwe opdracht'
            elif isinstance(item, jotihuntApiBase.Hint):
                r['url'] = settings.Settings().base_hint_url + item.ID
                r['soort'] = 'een nieuwe hint'
            elif isinstance(item, jotihuntApiBase.Nieuws):
                r['url'] = settings.Settings().base_nieuws_url + item.ID
                r['soort'] = 'nieuws'
            r['botan_soort'] = r['soort'].replace(' ', '_')
            return r

        jotihunt_message = 'Er is {soort} met de titel [{title}]({url})'

        def add_opdracht_reminder(opdracht, chat_ids):
            opdracht_id = opdracht.data.ID
            if opdracht_id not in self.reminders:
                self._reminders_lock.acquire()
                try:
                    self.reminders[opdracht_id] = Reminder(opdracht, chat_ids)
                finally:
                    self._reminders_lock.release()
        opdracht_updater = SingleUpdater(get_last_opdracht,
                                         get_jotihunt_kwargs, jotihunt_message,
                                         botan_id=self.botan_id_jotihunt,
                                         callback=add_opdracht_reminder)
        nieuws_updater = SingleUpdater(get_last_nieuws, get_jotihunt_kwargs,
                                       jotihunt_message,
                                       botan_id=self.botan_id_jotihunt)
        hint_updater = SingleUpdater(get_last_hint, get_jotihunt_kwargs,
                                     jotihunt_message,
                                     botan_id=self.botan_id_jotihunt)
        self.reminders = dict()
        self._opdrachten = SingleUpdateContainer([opdracht_updater])  # naam niet
        # veranderen
        self._nieuws = SingleUpdateContainer([nieuws_updater])  # naam niet veranderen
        self._hints = SingleUpdateContainer([hint_updater])  # naam niet veranderen
        self._error = set()  # naam niet veranderen
        self._punten = {'opdrachten': 0,
                        'hints': 0,
                        'hunts': 0,
                        'fotos': 0,
                        'totaal': 0}

        self._last_update = 0
        self.lastPhoto = None
        self.seenMail = set()
        self.lastHint = None
Ejemplo n.º 3
0
class MyUpdates:
    def __init__(self):

        self.seenHunts = dict()
        self.mail = imaplib.IMAP4_SSL('imap.gmail.com')
        self.mail.login(settings.Settings().rpmail_username,
                        settings.Settings().rpmail_pass)
        self.mail.select('INBOX')
        self.bot = None
        self.botan = Botan(settings.Settings().botan_key)

        # sets met chat_ids die updates willen ontvangen.
        self._A = set()  # naam niet veranderen
        self._B = set()  # naam niet veranderen
        self._C = set()  # naam niet veranderen
        self._D = set()  # naam niet veranderen
        self._E = set()  # naam niet veranderen
        self._F = set()  # naam niet veranderen
        self._X = set()  # naam niet veranderen
        self._photos = set()  # naam niet veranderen
        self._opdrachten = set()  # naam niet veranderen
        self._nieuws = set()  # naam niet veranderen
        self._error = set()  # naam niet veranderen
        self._hints = set()  # naam niet veranderen
        self._punten = {'opdrachten': 0,
                        'hints': 0,
                        'hunts': 0,
                        'fotos': 0,
                        'totaal': 0}

        self._last_update = 0
        self.lastA = None
        self.lastB = None
        self.lastC = None
        self.lastD = None
        self.lastE = None
        self.lastF = None
        self.lastX = None
        self.lastPhoto = None
        self.lastOpdracht = None
        self.lastNieuws = None
        self.lastStatus = None
        self.seenMail = set()
        self.lastHint = None
        self.rp_api = RPApi.get_instance(settings.Settings().rp_username,
                                         settings.Settings().rp_pass)

    def to_dict(self):
        return {'A': self._A,
                'B': self._B,
                'C': self._C,
                'D': self._D,
                'E': self._E,
                'F': self._F,
                'X': self._X,
                'photos': self._photos,
                'opdrachten': self._opdrachten,
                'nieuws': self._nieuws,
                'error': self._error,
                'hints': self._hints,
                'punten': self._punten
                }

    @void_no_crash()
    def from_dict(self, d):
        for k in d:
            setattr(self, '_' + k, d[k])

    @void_no_crash()
    def update(self):
        if self.has_bot() and \
                (self._last_update is None or
                 abs(time.time() - self._last_update) > 60):
            self.update_vos_last()
            self.update_vos_status()
            self.update_nieuws()
            self.update_opdrachten()
            self.update_hint()
            self.update_foto_opdracht()
            self.update_mail()
            self.update_hunts()
            self._last_update = time.time()
        else:
            return

    def save(self):
        d = self.to_dict()
        with open(UPDATER_FILE, 'wb') as file:
            pickle.dump(d, file)

    @void_no_crash()
    def add_bot(self, bot):
        self.bot = bot

    def has_bot(self):
        return self.bot is not None

    def check_updates(self, chat_id):
        if chat_id in self._A:
            yield 'Alpha'
        if chat_id in self._B:
            yield 'Bravo'
        if chat_id in self._C:
            yield 'Charlie'
        if chat_id in self._D:
            yield 'Delta'
        if chat_id in self._E:
            yield 'Echo'
        if chat_id in self._F:
            yield 'Foxtrot'
        if chat_id in self._X:
            yield 'X-Ray'
        if chat_id in self._error:
            yield 'Errors'
        if chat_id in self._nieuws:
            yield 'Nieuws'
        if chat_id in self._opdrachten:
            yield 'Opdrachten'
        if chat_id in self._photos:
            yield 'photos'
        if chat_id in self._hints:
            yield 'hints'

    @void_no_crash()
    def add_chat(self, chat_id, update_type):
        if update_type == ALPHA:
            self._A.add(chat_id)
        elif update_type == BRAVO:
            self._B.add(chat_id)
        elif update_type == CHARLIE:
            self._C.add(chat_id)
        elif update_type == DELTA:
            self._D.add(chat_id)
        elif update_type == ECHO:
            self._E.add(chat_id)
        elif update_type == FOXTROT:
            self._F.add(chat_id)
        elif update_type == XRAY:
            self._X.add(chat_id)
        elif update_type == PHOTOS:
            self._photos.add(chat_id)
        elif update_type == OPDRACHTEN:
            self._opdrachten.add(chat_id)
        elif update_type == NIEUWS:
            self._nieuws.add(chat_id)
        elif update_type == ERROR:
            self._error.add(chat_id)
        elif update_type == HINTS:
            self._hints.add(chat_id)

    @void_no_crash()
    def remove_chat(self, chat_id, update_type):
        if update_type == ALPHA:
            self._A.remove(chat_id)
        elif update_type == BRAVO:
            self._B.remove(chat_id)
        elif update_type == CHARLIE:
            self._C.remove(chat_id)
        elif update_type == DELTA:
            self._D.remove(chat_id)
        elif update_type == ECHO:
            self._E.remove(chat_id)
        elif update_type == FOXTROT:
            self._F.remove(chat_id)
        elif update_type == XRAY:
            self._X.remove(chat_id)
        elif update_type == PHOTOS:
            self._photos.remove(chat_id)
        elif update_type == OPDRACHTEN:
            self._opdrachten.remove(chat_id)
        elif update_type == NIEUWS:
            self._nieuws.remove(chat_id)
        elif update_type == ERROR:
            self._error.remove(chat_id)
        elif update_type == HINTS:
            self._hints.remove(chat_id)

    @void_no_crash()
    def set_updates(self, chat_id, dg, status):
        if status:
            self.add_chat(chat_id, dg)
        else:
            self.remove_chat(chat_id, dg)

    @void_no_crash()
    def update_vos_last(self):
        vos_a = self.rp_api.vos('a')
        vos_b = self.rp_api.vos('b')
        vos_c = self.rp_api.vos('c')
        vos_d = self.rp_api.vos('d')
        vos_e = self.rp_api.vos('e')
        vos_f = self.rp_api.vos('f')
        vos_x = self.rp_api.vos('x')
        if self.lastA != vos_a and self.has_bot():
            self.lastA = vos_a
            for chat_id in self._A:
                self.new_vos(chat_id, 'Alpha', vos_a)
        if self.lastB != vos_b and self.has_bot():
            self.lastB = vos_b
            for chat_id in self._B:
                self.new_vos(chat_id, 'Bravo', vos_b)
        if self.lastC != vos_c and self.has_bot():
            self.lastC = vos_c
            for chat_id in self._C:
                self.new_vos(chat_id, 'Charlie', vos_c)
        if self.lastD != vos_d and self.has_bot():
            self.lastD = vos_d
            for chat_id in self._D:
                self.new_vos(chat_id, 'Delta', vos_d)
        if self.lastE != vos_e and self.has_bot():
            self.lastE = vos_e
            for chat_id in self._E:
                self.new_vos(chat_id, 'Echo', vos_e)
        if self.lastF != vos_f and self.has_bot():
            self.lastF = vos_f
            for chat_id in self._F:
                self.new_vos(chat_id, 'Foxtrot', vos_f)
        if self.lastX != vos_x and self.has_bot():
            self.lastX = vos_x
            for chat_id in self._X:
                self.new_vos(chat_id, 'X-Ray', vos_x)

    @void_no_crash()
    def new_vos(self, chat_id, deelgebied, vos):
        if vos['icon'] == '3':
            m = self.bot.sendMessage(chat_id, deelgebied + " Is gespot.\n " +
                                     "extra info: " + vos['extra'] + '\n' +
                                     'opmerking/adres: ' + vos['opmerking'])
        elif vos['icon'] == '4':
            m = self.bot.sendMessage(chat_id, deelgebied + " is geshunt.\n" +
                                     "extra info: " + vos['extra'] + '\n' +
                                     'opmerking/adres: ' + vos['opmerking'])
        else:
            m = self.bot.sendMessage(chat_id,
                                     "Er is een Hint ingevoerd voor " + str(
                                         deelgebied) + '\n' +
                                     'extra info: ' + str(
                                         vos['extra']) + '\n' +
                                     'opmerking/adres: ' + str(
                                         vos['opmerking']))
        self.bot.sendLocation(chat_id, latitude=vos['latitude'],
                              longitude=vos['longitude'])
        self.botan.track(m, 'newLoc_' + deelgebied + '_' + vos['icon'])

    @void_no_crash()
    def update_vos_status(self):
        response = jotihuntApi.get_vossen()
        curr_status = response.data

        def send_update(chat_id, vos, new_status):
            if new_status is None:
                return
            m = self.bot.sendSticker(chat_id, status_plaatjes[vos][new_status][
                'file_id'])
            self.botan.track(m, 'vos_status_' + vos + '_' + new_status)
            send_cloudmessage(vos, new_status)

        def extract_status(vos):
            return curr_status[vos[0].lower()].status

        def send_a():
            for chat_id in self._A:
                vos = 'a'
                send_update(chat_id, vos, extract_status(vos))

        def send_b():
            for chat_id in self._B:
                vos = 'b'
                send_update(chat_id, vos, extract_status(vos))

        def send_c():
            for chat_id in self._C:
                vos = 'c'
                send_update(chat_id, vos, extract_status(vos))

        def send_d():
            for chat_id in self._D:
                vos = 'd'
                send_update(chat_id, vos, extract_status(vos))

        def send_e():
            for chat_id in self._E:
                vos = 'e'
                send_update(chat_id, vos, extract_status(vos))

        def send_f():
            for chat_id in self._F:
                vos = 'f'
                send_update(chat_id, vos, extract_status(vos))

        def send_x():
            for chat_id in self._X:
                vos = 'x'
                send_update(chat_id, vos, extract_status(vos))

        if self.lastStatus is None:
            send_a()
            send_b()
            send_c()
            send_d()
            send_e()
            send_f()
            send_x()
            self.lastStatus = curr_status
        else:
            for k, item in enumerate(curr_status):
                if item.team == 'Alpha' and item['status'] != \
                        extract_status('a')['status']:
                    send_a()
                if item.team == 'Bravo' and item['status'] != \
                        extract_status('b')['status']:
                    send_b()
                if item.team == 'Charlie' and item['status'] != \
                        extract_status('c')['status']:
                    send_c()
                if item.team == 'Delta' and item['status'] != \
                        extract_status('d')['status']:
                    send_d()
                if item.team == 'Echo' and item['status'] != \
                        extract_status('e')['status']:
                    send_e()
                if item.team == 'Foxtrot' and item['status'] != \
                        extract_status('f')['status']:
                    send_f()
                self.lastStatus = curr_status

    @void_no_crash()
    def update_nieuws(self):
        nieuws = jotihuntApi.get_nieuws_lijst().data
        if nieuws and nieuws[0] != self.lastNieuws:
            item = nieuws[0].data
            message = 'Er is nieuws met de titel [{title}]({url})'.format(
                title=item.titel,
                url=settings.Settings().base_nieuws_url + item.ID)
            for chat_id in self._nieuws:
                self.bot.sendMessage(chat_id, message,
                                     parse_mode=ParseMode.MARKDOWN)
            self.lastNieuws = nieuws[0]

    @void_no_crash()
    def update_opdrachten(self):
        opdrachten = jotihuntApi.get_opdrachten().data
        if opdrachten and opdrachten[0] != self.lastOpdracht:
            opdracht = opdrachten[0].data
            message = 'Er is nieuws met de titel [{title}]({url})'.format(
                title=opdracht.titel,
                url=settings.Settings().base_opdracht_url + opdracht.ID)
            for chat_id in self._opdrachten:
                self.bot.sendMessage(chat_id, message,
                                     parse_mode=ParseMode.MARKDOWN)
            self.lastOpdracht = opdrachten[0]

    @void_no_crash()
    def update_hint(self):
        hints = jotihuntApi.get_hints().data
        if hints and hints[0] != self.lastHint:
            hint = hints[0].data
            message = 'Er is een hint met de titel [{title}]({url})'
            message = message.format(title=hint.titel,
                                     url=settings.Settings().base_hint_url +
                                     hint.ID)
            for chat_id in self._hints:
                self.bot.sendMessage(chat_id, message,
                                     parse_mode=ParseMode.MARKDOWN)
            self.lastHint = hints[0]

    @void_no_crash()
    def update_foto_opdracht(self):
        pass

    @void_no_crash()
    def update_mail(self):
        i = 1
        found = []
        self.mail.search(None, 'ALL')
        while True:
            j = bytes(str(i), 'utf8')
            try:
                status, mail = self.mail.fetch(j, '(RFC822)')
            except Exception as e:
                self.error(e, 'update_mail')
                break
            if mail[0] is None:
                break
            raw_text = mail[0][1].decode('utf8')
            result = re.search('de opdracht(.)*?deze opdracht', raw_text, re.S)
            if result is not None and result.group(0) not in self.seenMail:
                found.append(result.group(0))
                self.seenMail.add(result)
            result = re.search(
                'Jullie tegenhunt(.)*?mag uiteraard wel',
                raw_text, re.S)
            if result is not None and result.group(0) not in self.seenMail:
                found.append(result.group(0))
                self.seenMail.add(result.group(0))
            i += 1
        for update in found:
            for chat_id in self._nieuws:
                self.bot.sendMessage(chat_id,
                                     'Er is een mail van de organisatie:\n'
                                     + str(update))

    @void_no_crash()
    def update_hunts(self):
        h = get_hunts()
        hd = to_dict(*h)
        for k, v in enumerate(hd):
            if k not in self.seenHunts:
                if str(k).lower().startswith('a'):
                    for chat_id in self._A:
                        self.bot.sendMessage(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                elif str(k).lower().startswith('b'):
                    for chat_id in self._B:
                        self.bot.sendMessage(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                elif str(k).lower().startswith('c'):
                    for chat_id in self._C:
                        self.bot.sendMessage(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                elif str(k).lower().startswith('d'):
                    for chat_id in self._D:
                        self.bot.sendMessage(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                elif str(k).lower().startswith('e'):
                    for chat_id in self._E:
                        self.bot.sendMessage(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                elif str(k).lower().startswith('f'):
                    for chat_id in self._F:
                        self.bot.sendMessage(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                self.seenHunts[k] = v
            else:
                if v['status'] != self.seenHunts[k]['status']:
                    message = 'de status van code: {code} is aangepast op de website. Van {old_status} naar {new_status}. Het aantal punten voor deze hunt is nu: {punten}'
                    message = message.format(code=str(k),
                                             old_status=str(
                                                 self.seenHunts[k][
                                                     'status']),
                                             new_status=str(v['status']
                                                            ),
                                             puntten=str(v['punten']))
                    if str(k).lower().startswith('a'):
                        for chat_id in self._A:
                            self.bot.sendMessage(chat_id, message)
                    elif str(k).lower().startswith('b'):
                        for chat_id in self._B:
                            self.bot.sendMessage(chat_id, message)
                    elif str(k).lower().startswith('c'):
                        for chat_id in self._C:
                            self.bot.sendMessage(chat_id, message)
                    elif str(k).lower().startswith('d'):
                        for chat_id in self._D:
                            self.bot.sendMessage(chat_id, message)
                    elif str(k).lower().startswith('e'):
                        for chat_id in self._E:
                            self.bot.sendMessage(chat_id, message)
                    elif str(k).lower().startswith('f'):
                        for chat_id in self._F:
                            self.bot.sendMessage(chat_id, message)
                    else:
                        for chat_id in self._nieuws:
                            self.bot.sendMessage(chat_id, message)
                    self.seenHunts[k] = v

    @void_no_crash()
    def error(self, e, func_name):
        logging.info('updates error send to user:'******' ' + func_name)
        for chat_id in self._error:
            if self.has_bot():
                self.bot.sendMessage(chat_id,
                                     "er is een error opgetreden:\n" + str(
                                         func_name) + '\n' + str(e))
Ejemplo n.º 4
0
class MyUpdates:
    def __init__(self):
        self._reminders_lock = threading.Lock()
        self.mail = imaplib.IMAP4_SSL('imap.gmail.com')
        self.seenHunts = dict()
        self.bot = None
        self.botan = Botan(settings.Settings().botan_key)
        self.rp_api = RPApi.get_instance(settings.Settings().rp_username,
                                         settings.Settings().rp_pass)
        self.messages = []  # list of tuples (int, str, str, tuple, dict)

        def get_kwargs_vos(new_item):
            if new_item['icon'] == '3':
                new_item['soort'] = 'Spot'
            elif new_item['icon'] == '4':
                new_item['soort'] = 'Hunt'
            else:
                new_item['soort'] = 'Hint'
            new_item['team_upper'] = new_item['team'].upper()
            new_item['tijd'] = new_item['datetime'][11:]
            return new_item.data

        def get_kwargs_vos_status(new_item):
            new_item['dg'] = new_item['team'][0].lower()
            return new_item._data

        def send_location(vos, chat_ids):
            bot = get_updates().bot
            if bot is not None:
                for chat_id in chat_ids:
                    bot.sendLocation(chat_id, latitude=vos['latitude'],
                                     longitude=vos['longitude'])

        def send_status_sticker(status, chat_ids):
            bot = get_updates().bot
            vos = status['dg']
            new_status = status['status']
            if bot is not None:
                for chat_id in chat_ids:
                    bot.sendSticker(chat_id,
                                    status_plaatjes[vos][new_status]['file_id']
                                    )
            send_cloudmessage(vos, new_status)

        message_vos = 'er is een {soort} ingevoerd voor {team}.\n' \
                      ' extra info: {extra}\n ' \
                      'opmerking/adres: {opmerking}\n' \
                      'tijd: {tijd}\n' \
                      'link: http://jotihunt2016.area348.nl/map.php?gebied=' \
                      '{team_upper}'
        message_vos_status = 'Er is een nieuwe status voor {team}'
        self.botan_id_vos = 'newLoc_{team}_{soort}'
        self.botan_id_vos_status = 'newStatus_{dg}_{status}'

        def get_retriever(dg):
            def retriever():
                return self.rp_api.vos(dg)
            return retriever

        def get_retriever_status(dg):
            def retriever():
                return jotihuntApi.get_vossen().data[dg]
            return retriever

        for dg in ['a', 'b', 'c', 'd', 'e', 'f', 'x']:
            retr1 = get_retriever(dg)
            updater_rp = SingleUpdater(retr1,
                                       get_kwargs_vos, message_vos,
                                       botan_id=self.botan_id_vos+'_'+dg,
                                       callback=send_location)
            retr = get_retriever_status(dg)
            updater_status = SingleUpdater(retr, get_kwargs_vos_status,
                                           message_vos_status,
                                           botan_id=self.botan_id_vos_status
                                           + '_'+dg,
                                           callback=send_status_sticker)
            if dg == 'a':
                self._A = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'b':
                self._B = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'c':
                self._C = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'd':
                self._D = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'e':
                self._E = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'f':
                self._F = SingleUpdateContainer([updater_rp, updater_status])
            elif dg == 'x':
                self._X = SingleUpdateContainer([updater_rp, updater_status])

        self._photos = set()  # naam niet veranderen
        get_last_opdracht = lambda: jotihuntApi.get_opdrachten().data[0]
        get_last_nieuws = lambda: jotihuntApi.get_nieuws_lijst().data[0]
        get_last_hint = lambda: jotihuntApi.get_hints().data[0]
        self.botan_id_jotihunt = 'new_{botan_soort}'

        def get_jotihunt_kwargs(new_response):
            r = dict()
            item = new_response.data
            r['title'] = item.titel
            if isinstance(item, jotihuntApiBase.Opdracht):
                r['url'] = settings.Settings().base_opdracht_url + item.ID
                r['soort'] = 'een nieuwe opdracht'
            elif isinstance(item, jotihuntApiBase.Hint):
                r['url'] = settings.Settings().base_hint_url + item.ID
                r['soort'] = 'een nieuwe hint'
            elif isinstance(item, jotihuntApiBase.Nieuws):
                r['url'] = settings.Settings().base_nieuws_url + item.ID
                r['soort'] = 'nieuws'
            r['botan_soort'] = r['soort'].replace(' ', '_')
            return r

        jotihunt_message = 'Er is {soort} met de titel [{title}]({url})'

        def add_opdracht_reminder(opdracht, chat_ids):
            opdracht_id = opdracht.data.ID
            if opdracht_id not in self.reminders:
                self._reminders_lock.acquire()
                try:
                    self.reminders[opdracht_id] = Reminder(opdracht, chat_ids)
                finally:
                    self._reminders_lock.release()
        opdracht_updater = SingleUpdater(get_last_opdracht,
                                         get_jotihunt_kwargs, jotihunt_message,
                                         botan_id=self.botan_id_jotihunt,
                                         callback=add_opdracht_reminder)
        nieuws_updater = SingleUpdater(get_last_nieuws, get_jotihunt_kwargs,
                                       jotihunt_message,
                                       botan_id=self.botan_id_jotihunt)
        hint_updater = SingleUpdater(get_last_hint, get_jotihunt_kwargs,
                                     jotihunt_message,
                                     botan_id=self.botan_id_jotihunt)
        self.reminders = dict()
        self._opdrachten = SingleUpdateContainer([opdracht_updater])  # naam niet
        # veranderen
        self._nieuws = SingleUpdateContainer([nieuws_updater])  # naam niet veranderen
        self._hints = SingleUpdateContainer([hint_updater])  # naam niet veranderen
        self._error = set()  # naam niet veranderen
        self._punten = {'opdrachten': 0,
                        'hints': 0,
                        'hunts': 0,
                        'fotos': 0,
                        'totaal': 0}

        self._last_update = 0
        self.lastPhoto = None
        self.seenMail = set()
        self.lastHint = None

    def to_dict(self):
        return {'A': self._A.chat_ids,
                'B': self._B.chat_ids,
                'C': self._C.chat_ids,
                'D': self._D.chat_ids,
                'E': self._E.chat_ids,
                'F': self._F.chat_ids,
                'X': self._X.chat_ids,
                'photos': self._photos,
                'opdrachten': self._opdrachten.chat_ids,
                'nieuws': self._nieuws.chat_ids,
                'error': self._error,
                'hints': self._hints.chat_ids,
                }

    @void_no_crash()
    def from_dict(self, d):
        for k in d:
            s =getattr(self, '_' + k)
            for chat_id in d[k]:
                s.add(chat_id)

    @void_no_crash()
    def update(self):
        if self._last_update is None or abs(time.time() -
                                                    self._last_update) > 60:
            threads = [threading.Thread(target=self._A.update),
                       threading.Thread(target=self._B.update),
                       threading.Thread(target=self._C.update),
                       threading.Thread(target=self._D.update),
                       threading.Thread(target=self._E.update),
                       threading.Thread(target=self._F.update),
                       threading.Thread(target=self._X.update),
                       threading.Thread(target=self._nieuws.update),
                       threading.Thread(target=self._opdrachten.update),
                       threading.Thread(target=self._hints.update),
                       threading.Thread(target=self.remind)]
            for t in threads:
                t.start()
            self.update_foto_opdracht()
            self.update_mail()
            self.update_hunts()
            self._last_update = time.time()
            start = time.time()
            while threads:
                if time.time() - start > 300:
                    self.send_message(-158130982, 'timeout error opgetrden '
                                                  'tijdens updaten. updaten '
                                                  'duurde meer dan 300 '
                                                  'seconden. waarschijnlijk '
                                                  'is het een goed idee om '
                                                  'de bot opnieuw op te '
                                                  'starten.')
                    raise TimeoutError('meer dan 5 minuten over een update '
                                       'gedaan.', len(threads))
                t = threads.pop(0)
                t.join(1)
                if t.isAlive():
                    threads.append(t)

        else:
            return

    @void_no_crash()
    def remind(self):
        self._reminders_lock.acquire()
        try:
            for opdracht_id in self.reminders:
                self.reminders[opdracht_id].remind()
        finally:
            self._reminders_lock.release()

    @void_no_crash()
    def save(self):
        d = self.to_dict()
        with open(UPDATER_FILE, 'wb') as file:
            pickle.dump(d, file)

    @void_no_crash()
    def add_bot(self, bot):
        if self.bot is None:
            self.bot = bot
        for m in self.messages:
            chat_id, mesg, botan_id, args, kwargs = m
            mes = bot.send_message(chat_id, mesg, *args, **kwargs)
            if botan_id is not None:
                self.botan.track(mes, str(botan_id))
        self.messages = []

    def has_bot(self):
        return self.bot is not None

    def check_updates(self, chat_id):
        if chat_id in self._A:
            yield 'Alpha'
        if chat_id in self._B:
            yield 'Bravo'
        if chat_id in self._C:
            yield 'Charlie'
        if chat_id in self._D:
            yield 'Delta'
        if chat_id in self._E:
            yield 'Echo'
        if chat_id in self._F:
            yield 'Foxtrot'
        if chat_id in self._X:
            yield 'X-Ray'
        if chat_id in self._error:
            yield 'Errors'
        if chat_id in self._nieuws:
            yield 'Nieuws'
        if chat_id in self._opdrachten:
            yield 'Opdrachten'
        if chat_id in self._photos:
            yield 'photos'
        if chat_id in self._hints:
            yield 'hints'

    @void_no_crash()
    def add_chat(self, chat_id, update_type):
        if update_type == ALPHA:
            self._A.add(chat_id)
        elif update_type == BRAVO:
            self._B.add(chat_id)
        elif update_type == CHARLIE:
            self._C.add(chat_id)
        elif update_type == DELTA:
            self._D.add(chat_id)
        elif update_type == ECHO:
            self._E.add(chat_id)
        elif update_type == FOXTROT:
            self._F.add(chat_id)
        elif update_type == XRAY:
            self._X.add(chat_id)
        elif update_type == PHOTOS:
            self._photos.add(chat_id)
        elif update_type == OPDRACHTEN:
            self._opdrachten.add(chat_id)
        elif update_type == NIEUWS:
            self._nieuws.add(chat_id)
        elif update_type == ERROR:
            self._error.add(chat_id)
        elif update_type == HINTS:
            self._hints.add(chat_id)

    @void_no_crash()
    def remove_chat(self, chat_id, update_type):
        if update_type == ALPHA:
            self._A.remove(chat_id)
        elif update_type == BRAVO:
            self._B.remove(chat_id)
        elif update_type == CHARLIE:
            self._C.remove(chat_id)
        elif update_type == DELTA:
            self._D.remove(chat_id)
        elif update_type == ECHO:
            self._E.remove(chat_id)
        elif update_type == FOXTROT:
            self._F.remove(chat_id)
        elif update_type == XRAY:
            self._X.remove(chat_id)
        elif update_type == PHOTOS:
            self._photos.remove(chat_id)
        elif update_type == OPDRACHTEN:
            self._opdrachten.remove(chat_id)
        elif update_type == NIEUWS:
            self._nieuws.remove(chat_id)
        elif update_type == ERROR:
            self._error.remove(chat_id)
        elif update_type == HINTS:
            self._hints.remove(chat_id)

    @void_no_crash()
    def set_updates(self, chat_id, dg, status):
        if status:
            self.add_chat(chat_id, dg)
        else:
            self.remove_chat(chat_id, dg)

    @void_no_crash()
    def update_foto_opdracht(self, new_update_item=None):
        pass

    @void_no_crash()
    def update_mail(self, new_update_item=None):
        i = 1
        found = []
        gmail = imaplib.IMAP4_SSL('imap.gmail.com')
        gmail.login(settings.Settings().rpmail_username,
                        settings.Settings().rpmail_pass)
        gmail.select('INBOX')
        gmail.search(None, 'ALL')
        while True:
            j = bytes(str(i), 'utf8')
            try:
                status, mail = gmail.fetch(j, '(RFC822)')
            except Exception as e:
                type_, value_, traceback_ = sys.exc_info()
                get_updates().error(e, 'update_mail', (type_, value_, traceback_))
                break
            if mail[0] is None:
                break
            raw_text = mail[0][1].decode('utf8')
            result = re.search('de opdracht(.)*?deze opdracht', raw_text, re.S)
            if result is not None and result.group(0) not in self.seenMail:
                found.append(result.group(0))
                self.seenMail.add(result.group(0))
            result = re.search(
                'Jullie tegenhunt(.)*?mag uiteraard wel',
                raw_text, re.S)
            if result is not None and result.group(0) not in self.seenMail:
                found.append(result.group(0))
                self.seenMail.add(result.group(0))
            i += 1
        for update in found:
            for chat_id in self._nieuws:
                self.send_message(chat_id,
                                     'Er is een mail van de organisatie:\n'
                                     + str(update))

    @void_no_crash()
    def update_hunts(self, new_update_item=None):
        if settings.Settings().phpsessid is None:
            return
        h = get_hunts()
        hd = to_dict(*h)
        for k, v in enumerate(hd):
            if k not in self.seenHunts:
                if str(k).lower().startswith('a'):
                    for chat_id in self._A:
                        self.send_message(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                elif str(k).lower().startswith('b'):
                    for chat_id in self._B:
                        self.send_message(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                elif str(k).lower().startswith('c'):
                    for chat_id in self._C:
                        self.send_message(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                elif str(k).lower().startswith('d'):
                    for chat_id in self._D:
                        self.send_message(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                elif str(k).lower().startswith('e'):
                    for chat_id in self._E:
                        self.send_message(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                elif str(k).lower().startswith('f'):
                    for chat_id in self._F:
                        self.send_message(chat_id, 'code: ' + str(
                            k) + ' is ingevoerd op de website')
                self.seenHunts[k] = v
            else:
                if v['status'] != self.seenHunts[k]['status']:
                    message = 'de status van code: {code} is aangepast op de website. Van {old_status} naar {new_status}. Het aantal punten voor deze hunt is nu: {punten}'
                    message = message.format(code=str(k),
                                             old_status=str(
                                                 self.seenHunts[k][
                                                     'status']),
                                             new_status=str(v['status']
                                                            ),
                                             puntten=str(v['punten']))
                    if str(k).lower().startswith('a'):
                        for chat_id in self._A:
                            self.send_message(chat_id, message)
                    elif str(k).lower().startswith('b'):
                        for chat_id in self._B:
                            self.send_message(chat_id, message)
                    elif str(k).lower().startswith('c'):
                        for chat_id in self._C:
                            self.send_message(chat_id, message)
                    elif str(k).lower().startswith('d'):
                        for chat_id in self._D:
                            self.send_message(chat_id, message)
                    elif str(k).lower().startswith('e'):
                        for chat_id in self._E:
                            self.send_message(chat_id, message)
                    elif str(k).lower().startswith('f'):
                        for chat_id in self._F:
                            self.send_message(chat_id, message)
                    else:
                        for chat_id in self._nieuws:
                            self.send_message(chat_id, message)
                    self.seenHunts[k] = v

    def error(self, e, func_name, tb=None):
        logging.info('updates error send to user:'******' ' + func_name)
        for chat_id in self._error:
            tb_s = ''
            if tb is not None:
                ex = traceback.format_exception(*tb)
                for l in ex:
                    tb_s += l
            message = "er is een error opgetreden:\n {funcname}\n{e}\n"\
                      "{clse}\n {tb}".format(funcname=str(func_name),
                                             e=str(e), clse=e.__class__,
                                             tb=tb_s)
            print(message)
            self.send_message(chat_id, message)

    @void_no_crash()
    def to_all(self, message):
        self.update()
        d = self.to_dict()
        chat_ids = set()
        for key in d:
            if type(d[key]) == set:
                for chat_id in d[key]:
                    chat_ids.add(chat_id)
        for chat_id in chat_ids:
            self.send_message(chat_id, message)

    def send_message(self, chat_id, message, *args, botan_id=None, **kwargs):
        message = message[:4096]
        if self.bot is None:
            self.messages.append((chat_id, message, botan_id, args, kwargs))
        else:
            m = self.bot.sendMessage(chat_id, message, *args, **kwargs)
            if botan_id is not None:
                self.botan.track(m, botan_id)