Exemple #1
0
    def __init__(  # pylint: disable=too-many-arguments
            self, root: Path, config: Config, url: str, username: str,
            password: str, calendar: str, **kwargs: Any):
        super().__init__(root, config, **kwargs)

        self.client = DAVClient(url=url, username=username, password=password)
        self.calendar = calendar
Exemple #2
0
def main():
    """Command line tool to download from CalDAV to Remind"""

    parser = ArgumentParser(description='Command line tool to download from CalDAV to Remind')
    parser.add_argument('-d', '--delete', action='store_true', help='Delete old events')
    parser.add_argument('-r', '--davurl', required=True, help='The URL of the CalDAV server')
    parser.add_argument('-u', '--davuser', help='The username for the CalDAV server')
    parser.add_argument('-p', '--davpass', help='The password for the CalDAV server')
    parser.add_argument('-i', '--insecure', action='store_true', help='Ignore SSL certificate')
    parser.add_argument('remfile', nargs='?', default=expanduser('~/.reminders'),
                        help='The Remind file to process (default: ~/.reminders)')
    args = parser.parse_args()

    # create empty file if it does not exist
    open(args.remfile, 'a')

    rem = Remind(args.remfile)
    ldict = set(rem.get_uids())

    if args.davuser and args.davpass:
        user = args.davuser
        passwd = args.davpass
    else:
        try:
            (user, _, passwd) = netrc().authenticators(urlparse(args.davurl).netloc)
        except (IOError, TypeError):
            if not args.davuser:
                print('dav2rem: Error, argument -u/--davuser or netrc is required')
                return 1
            user = args.davuser
            try:
                from keyring import get_password
                passwd = get_password(urlparse(args.davurl).netloc, user)
            except ImportError:
                passwd = None
            if not passwd:
                passwd = getpass()

    client = DAVClient(args.davurl, username=user, password=passwd,
                       ssl_verify_cert=not args.insecure)
    calendar = Calendar(client, args.davurl)

    rdict = {splitext(basename(event.canonical_url))[0].replace('%40', '@'): event for event in calendar.events()}

    if args.delete:
        local = ldict - rdict.keys()
        for uid in local:
            rem.remove(uid)

    remote = rdict.keys() - ldict
    for uid in remote:
        vevent = rdict[uid]
        rem.append_vobject(readOne(vevent.data))
Exemple #3
0
def main():
    url = getenv(URL_ENV)
    username = getenv(USER_ENV)
    password = getenv(PASS_ENV)

    if url is None:
        url = input('URL: ')
    if username is None:
        username = input('Username: '******'Password: '******'Invalid URL or credentials.')
        exit(1)

    start = getenv(START_ENV)
    end = getenv(END_ENV)
    try:
        start = datetime.fromisoformat(start)
        end = datetime.fromisoformat(end)
    except ValueError:
        print(f'Invalid {START_ENV} or {END_ENV} value.')
        exit(1)

    if start is None:
        default_start = datetime(date.today().year, 1, 1)
        start = timeinput(
            f'Start time [{default_start.strftime("%Y-%m-%d %H:%M")}]: ',
            default_start)
    if end is None:
        default_end = datetime(date.today().year + 1, 1, 1)
        end = timeinput(
            f'End time [{default_end.strftime("%Y-%m-%d %H:%M")}]: ',
            default_end)

    for cal in principal.calendars():
        for ev in cal.date_search(start=start, end=end,
                                  expand=True):  # expand recurring events
            write_event(cal.name, ev)
        with open(join(calendar_folder(cal.name), CAL_NAME_FILE),
                  'w') as f:  # for importing
            f.write(cal.name)
        print(f'Exported events from calendar \'{cal.name}\'.')
Exemple #4
0
def main():
    url = getenv(URL_ENV)
    username = getenv(USER_ENV)
    password = getenv(PASS_ENV)

    if url is None:
        url = input('URL: ')
    if username is None:
        username = input('Username: '******'Password: '******'Invalid URL or credentials.')
        exit(1)

    parent_folder = getcwd()
    for path in listdir():
        if not (path.startswith(EXPORT_FOLDER_PREFIX) and isdir(path)):
            continue

        chdir(join(parent_folder, path))
        try:
            with open(CAL_NAME_FILE, 'r') as f:
                cal_name = f.readline().strip()
        except FileNotFoundError:
            print(
                f'Found directory {path} which matches the export folder schema but does not contain a \
                    {CAL_NAME_FILE} file.')
            continue

        print(f'Importing calendar \'{cal_name}\'...')
        calendar = available_calendars.get(cal_name,
                                           principal.make_calendar(cal_name))

        count = len(listdir())
        for i, path in enumerate(listdir()):
            if path.endswith('.ics'):
                with open(path, 'r') as f:
                    calendar.save_event(''.join(f.readlines()))
            print(f'\t{i}/{count}', end='\r')
Exemple #5
0
 def __init__(self, calendar=None, url=None):
     if not config.CALENDAR_ACTIVE:
         return
     self.url = url if url is not None else config.CALENDAR_URL
     self.client = DAVClient(self.url)
     self.principal = None
     for _ in range(config.CALENDAR_MAX_REQUESTS):
         try:
             self.principal = self.client.principal()
             break
         except Exception as exc:
             print("Got exception {} from caldav, retrying".format(
                 str(exc)))
     if self.principal is None:
         raise CalendarException(
             "Got {} CalDAV-error from the CalDAV server.".format(
                 config.CALENDAR_MAX_REQUESTS))
     if calendar is not None:
         self.calendar = self.get_calendar(calendar)
     else:
         self.calendar = calendar
Exemple #6
0
def change_calendar(request, calendar_id: int = None):
    if calendar_id:
        calendar = get_object_or_404(DavCalendar, id=calendar_id, user=request.user)
        form = DavCalendarForm(request.POST, instance=calendar, user=request.user)
    else:
        form = DavCalendarForm(request.POST, user=request.user)
    if form.is_valid():
        caldav_obj = form.save(commit=False)
        old_calendars = DavCalendar.objects.filter(user=request.user).exclude(id=calendar_id)
        exists = False
        # This is necessary as the urls are encrypted in the DB and can't filtered wherefore
        for old_calendar in old_calendars:
            if old_calendar.id != calendar_id and old_calendar.url == caldav_obj.url:
                exists = True
                break
        if not exists:
            try:
                calendar = Calendar(client=DAVClient(caldav_obj.url),
                                    url=caldav_obj.url)
                calendar.date_search(now(), now() + timedelta(hours=1))
                caldav_obj.user = request.user
                caldav_obj.save()
                return redirect('settings')
            except Exception as e:
                form.add_error(None, ugettext_lazy("Error getting Calendar: {}".format(str(e))))
        else:
            form.add_error(None, ugettext_lazy("This calendar is already configured"))
    elif 'delete' in request.POST:
        obj = get_object_or_404(DavCalendar, id=request.POST['delete'], user=request.user)
        obj.delete()
        return redirect('settings')
    return TemplateResponse(request, "caldav/caldav.html", {
        'calendar_form': form,
        'calendars': DavCalendar.objects.filter(user=request.user),
        'calendar_id': calendar_id,
        'edit': calendar_id is not None,
    })
Exemple #7
0
def get_caldav(choices: List[Choice], current_poll: Poll, user: BitpollUser,
               request):
    # calendar stuff
    events2 = []
    if not settings.CALENDAR_ENABLED or not (user.is_authenticated and
                                             current_poll.type == 'datetime'
                                             and choices):
        for choice in choices:
            events2.append([])
        return events2
    start = choices[0].date
    end = choices[-1].date

    # experimental: fetch calendar(s)
    events = []
    for calendar_obj in user.davcalendar_set.all():
        cache_key = "calendar_{}_events_{}-{}".format(calendar_obj.id, start,
                                                      end).replace(' ', '_')
        events_calendar = cache.get(cache_key)
        if events_calendar is None:
            events_calendar = []
            try:
                calendar = DavCalendar(client=DAVClient(calendar_obj.url),
                                       url=calendar_obj.url)
                appointments = calendar.date_search(start, end)
                for appointment in appointments:
                    ical = Calendar.from_ical(appointment.data)
                    for event in ical.walk():
                        if event.name == "VEVENT":
                            try:
                                if "DTEND" in event:
                                    end = event.decoded('DTEND')
                                else:
                                    duration = event.decoded("DURATION")
                                    if isinstance(duration, list):
                                        duration = duration[
                                            0]  # todo: use all elements?? what does it mean if there are more than one element?
                                    end = event.decoded('DTSTART') + duration
                                events_calendar.append({
                                    "DTSTART":
                                    event.decoded('DTSTART'),
                                    "DTEND":
                                    end,
                                    "NAME":
                                    event.get('summary').title(),
                                })
                            except (AttributeError, ValueError,
                                    TypeError) as e:
                                # we ignore the event we can not parse, but send it to sentry
                                try:
                                    from raven.contrib.django.raven_compat.models import client
                                    client.captureException()
                                except Exception:
                                    # if the sending of the error does fail we ignore it
                                    pass
                cache.set(cache_key, events_calendar)
            except AuthorizationError as e:
                messages.warning(
                    request,
                    ugettext_lazy(
                        'Could not access your calendar "%s" due to an authorization error'
                        % calendar_obj.name))
        events += events_calendar
    for choice in choices:
        ev_tmp = []
        for event in events:
            if isinstance(event['DTSTART'], type(choice.date)):
                # datetime
                if event['DTSTART'] <= choice.date and event[
                        'DTEND'] >= choice.date:
                    ev_tmp.append(event)
            else:
                # dates
                if event['DTSTART'] <= choice.date.date() <= event['DTEND']:
                    ev_tmp.append(event)
        events2.append(ev_tmp)
    return events2
Exemple #8
0
def main():
    """Command line tool to upload a Remind file to CalDAV"""

    parser = ArgumentParser(
        description='Command line tool to upload a Remind file to CalDAV')
    parser.add_argument(
        '-z',
        '--zone',
        default='Europe/Berlin',
        help='Timezone of Remind file (default: Europe/Berlin)')
    parser.add_argument(
        '-s',
        '--startdate',
        type=lambda s: parse(s).date(),
        default=date.today() - timedelta(weeks=12),
        help='Start offset for remind call (default: -12 weeks)')
    parser.add_argument(
        '-m',
        '--month',
        type=int,
        default=15,
        help=
        'Number of month to generate calendar beginning wit stadtdate (default: 15)'
    )
    parser.add_argument('-d',
                        '--delete',
                        action='store_true',
                        help='Delete old events')
    parser.add_argument('-r',
                        '--davurl',
                        required=True,
                        help='The URL of the CalDAV server')
    parser.add_argument('-u',
                        '--davuser',
                        help='The username for the CalDAV server')
    parser.add_argument('-p',
                        '--davpass',
                        help='The password for the CalDAV server')
    parser.add_argument('-i',
                        '--insecure',
                        action='store_true',
                        help='Ignore SSL certificate')
    parser.add_argument(
        'infile',
        nargs='?',
        default=expanduser('~/.reminders'),
        help='The Remind file to process (default: ~/.reminders)')
    parser.add_argument(
        '-o',
        '--old',
        default=None,
        help=
        'The old reference Remind file (entries not in the current one will be deleted from dav)'
    )
    args = parser.parse_args()

    zone = gettz(args.zone)
    # Manually set timezone name to generate correct ical files
    # (python-vobject tests for the zone attribute)
    zone.zone = args.zone

    if args.infile == '-':
        remind = Remind(args.infile, zone, args.startdate, args.month)
        vobject = remind.stdin_to_vobject(stdin.read())
    else:
        remind = Remind(args.infile, zone, args.startdate, args.month)
        vobject = remind.to_vobject()

    if hasattr(vobject, 'vevent_list'):
        ldict = {event.uid.value: event for event in vobject.vevent_list}
    else:
        ldict = {}

    if args.davuser and args.davpass:
        user = args.davuser
        passwd = args.davpass
    else:
        try:
            (user, _,
             passwd) = netrc().authenticators(urlparse(args.davurl).netloc)
        except (IOError, TypeError):
            if not args.davuser:
                print(
                    'rem2dav: Error, argument -u/--davuser or netrc is required'
                )
                return 1
            user = args.davuser
            try:
                from keyring import get_password
                passwd = get_password(urlparse(args.davurl).netloc, user)
            except ImportError:
                passwd = None
            if not passwd:
                passwd = getpass()

    client = DAVClient(args.davurl,
                       username=user,
                       password=passwd,
                       ssl_verify_cert=not args.insecure)
    calendar = Calendar(client, args.davurl)

    rdict = {
        splitext(basename(event.canonical_url))[0].replace('%40', '@'): event
        for event in calendar.events()
    }

    if args.old:
        old = Remind(args.old, zone, args.startdate, args.month)
        old_vobject = old.to_vobject()

        if hasattr(old_vobject, 'vevent_list'):
            odict = {
                event.uid.value: event
                for event in old_vobject.vevent_list
            }
            intersect = rdict.keys() & odict.keys()
            rdict = {key: rdict[key] for key in intersect}
        else:
            rdict = {}

    local = ldict.keys() - rdict.keys()
    for uid in local:
        ncal = iCalendar()
        ncal.add(ldict[uid])
        calendar.add_event(ncal.serialize())

    if args.delete or args.old:
        remote = rdict.keys() - ldict.keys()
        for uid in remote:
            rdict[uid].delete()