From 9381e246ce04a5fa4ebde5d97ad20b48e87249db Mon Sep 17 00:00:00 2001 From: Yessiest Date: Thu, 20 Jan 2022 02:51:39 +0400 Subject: [PATCH] initial commit --- README.md | 7 ++ decal | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 README.md create mode 100755 decal diff --git a/README.md b/README.md new file mode 100644 index 0000000..7231b64 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# decal - a simple calendar with caldav events + +# Dependencies +``` +pip install caldav +``` + diff --git a/decal b/decal new file mode 100755 index 0000000..025a4f9 --- /dev/null +++ b/decal @@ -0,0 +1,191 @@ +#!/usr/bin/python +import configparser +import datetime +import calendar +import caldav +import argparse +import os +import json +import re +config = configparser.ConfigParser() +Version = "%(prog)s 0.1" +configpath = os.getenv("HOME")+"/.config/decal.conf" +config.read(configpath) +#define arguments +today = datetime.date.today() +parser = argparse.ArgumentParser(description="Cal with events.") +parser.add_argument("year", + action="store", + default=today.year, + nargs="?", + type=int) +parser.add_argument("month", + action="store", + default=today.month, + nargs="?", + type=int) +parser.add_argument("day", + action="store", + default=today.day, + nargs="?", + type=int) +parser.add_argument("-v", "--version", + action="version", + version=Version, + help="Display the version of the program") +parser.add_argument("--json", + action="store_true", + help="Dump events output to json") +parser.add_argument("--create", + action="store_true", + help="Create a new event") +parser.add_argument("--calendar", + action="append", + help="Specify a calendar (or multiple calendars) to sync from") +parser.add_argument("-1", + action="store_true", + help="show only a single month (default)") +parser.add_argument("-3", + action="store_true", + help="show three months spanning the date") +parser.add_argument("-y", + action="store_true", + help="show the whole year") +parser.add_argument("-n", + action="store_const", + const=int, + help="show n months") + +args = vars(parser.parse_args()) + +#check some stuff, do some warnings, initiate the config, etc. +if not os.path.exists(configpath): + config['DEFAULT'] = {'uri': 'your caldap server here', + 'user': 'your username here', + 'password': 'your pass here'} + print("Creating an empty config in ~/.config/decal.conf") + with open(configpath,'w') as configfile: + config.write(configfile) + configfile.close() + print("To properly utilize decal, please fill out the fields in the config") + exit(1) + +for arg in ("user","password","uri"): + if not arg in config['DEFAULT']: + print("The config is incomplete, please check the \""+arg+"\" field") + exit(1) + +if config['DEFAULT']['uri'] == "your caldap server here": + print("To properly utilize decal, please fill out the fields in the config") + exit(1) + +#actual works begins here + +#generate the actual calendar, line by line, output an array of lines. +#it works trust me, idk what is happening in this one but it works. +def gencal(year,month,start_on_sunday=True,cell_modifier=lambda d: d,append_year=True): + firstweekday = 0 + if start_on_sunday: + firstweekday = 6 + cal = calendar.Calendar(firstweekday=firstweekday) + lines = [""]*6 + monthstart = False + counter = 0 + for date in cal.itermonthdates(year,month): + lines[counter//7] + day = str(date)[-2:] + if day == "01": + monthstart = not monthstart + if monthstart: + lines[counter//7] += cell_modifier(day) + else: + lines[counter//7] += " " + lines[counter//7] +=" " + counter+=1 + month = datetime.date(year,month,1).strftime("%B %Y") + padding = (len(lines[0])-len(month))//2 + rpadding = len(lines[0])%(padding+len(month)+padding) + if start_on_sunday: + lines.insert(0,"Su Mo Tu We Th Fr Sa ") + else: + lines.insert(0,"Mo Tu We Th Fr Sa Su ") + lines.insert(0,(" "*padding)+month+(" "*(padding+rpadding))) + lines[-1] += " "*(21-len(lines[-1])) + return lines + +color_names = { + "red":"0;31", + "green":"0;32", + "brown":"0;33", + "orange":"0;33", + "blue":"0;34", + "purple":"0;35", + "cyan":"0;36", + "yellow":"1;33", + "white":"1;37", + "blink":"5", + "bold":"1", + "italic":"3", + "underline":"4", + "inverse":"7", + "strikethrough":"9", + "light red":"1;31", + "light green":"1;32", + "light blue":"1;34", + "light purple":"1;36", + "light cyan":"0;37" +} +def colorize(text,color): + if color in color_names: + return "\033["+color_names[color]+"m"+text+"\033[0m" + elif re.match("(\d{1,3}),(\d{1,3}),(\d{1,3})",color): + color = "\\"+re.sub("(\d{1,3}),(\d{1,3}),(\d{1,3})","38;2;\\1;\\2;\\3m",color) + + return color+text+"\033[0m" + +def span(year,month,offset): + return year+((month+offset-1)//12),((month+offset-1)%12)+1 + +def getbounds(y,m,offset): + start = datetime.date(y,m,1) + postnextmonth = span(y,m,offset) + nextmonth = span(postnextmonth[0],postnextmonth[1],-1) + end = datetime.date(nextmonth[0], + nextmonth[1], + (datetime.date(postnextmonth[0],postnextmonth[1],1)-datetime.timedelta(days=1)).day) + return start,end + +start = None +end = None +if args["1"]: + start,end = getbounds(args["year"],args["month"],1) +elif args["3"]: + y,m = span(args["year"],args["month"],-1) + start,end = getbounds(y,m,3) +elif args["n"]: + start,end = getbounds(args["year"],args["month"],args["n"]) +else: + start,end = getbounds(args["year"],args["month"],1) + +client = caldav.DAVClient(url = config['DEFAULT']['uri'], + username = config['DEFAULT']['user'], + password = config['DEFAULT']['password']) +principal = client.principal() +calendars = principal.calendars() +if "calendar" in config['DEFAULT']: + calendars2 = [] + cals = config['DEFAULT']["calendar"].split(",") + for cal in calendars: + if cal.name in cal: + calendars2.append(cal) + calendars = calendars2 + + +events = [] +for calendar in calendars: + events_fetched = calendar.date_search(start,end) + for event in events_fetched: + if not event in events: + events.append(event) + +