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
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))
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}\'.')
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')
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
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, })
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
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()