"Catches up" on the missed updates while the client was offline.
        You should call this method after registering the event handlers
        so that the updates it loads can by processed by your script.

        This can also be used to forcibly fetch new updates if there are any.

async def catch_up(self):
        """
        "Catches up" on the missed updates while the client was offline.
        You should call this method after registering the event handlers
        so that the updates it loads can by processed by your script.

        This can also be used to forcibly fetch new updates if there are any.
        """
        pts, date = self._state_cache[None]
        self.session.catching_up = True
        try:
            while True:
                d = await self(functions.updates.GetDifferenceRequest(
                    pts, date, 0
                ))
                if isinstance(d, (types.updates.DifferenceSlice,
                                  types.updates.Difference)):
                    if isinstance(d, types.updates.Difference):
                        state = d.state
                    else:
                        state = d.intermediate_state

                    pts, date = state.pts, state.date
                    self._handle_update(types.Updates(
                        users=d.users,
                        chats=d.chats,
                        date=state.date,
                        seq=state.seq,
                        updates=d.other_updates + [
                            types.UpdateNewMessage(m, 0, 0)
                            for m in d.new_messages
                        ]
                    ))

                    # TODO Implement upper limit (max_pts)
                    # We don't want to fetch updates we already know about.
                    #
                    # We may still get duplicates because the Difference
                    # contains a lot of updates and presumably only has
                    # the state for the last one, but at least we don't
                    # unnecessarily fetch too many.
                    #
                    # updates.getDifference's pts_total_limit seems to mean
                    # "how many pts is the request allowed to return", and
                    # if there is more than that, it returns "too long" (so
                    # there would be duplicate updates since we know about
                    # some). This can be used to detect collisions (i.e.
                    # it would return an update we have already seen).
                else:
                    if isinstance(d, types.updates.DifferenceEmpty):
                        date = d.date
                    elif isinstance(d, types.updates.DifferenceTooLong):
                        pts = d.pts
                    break
        except (ConnectionError, asyncio.CancelledError):
            pass
        finally:
            # TODO Save new pts to session
            self._state_cache._pts_date = (pts, date)
            self.session.catching_up = False