CalenCraft is a basic flask application that can merge multiple ics links into one, creating a single consolidated calendar.
- Combine multiple ics files into one subscribable link
- Filters to include or exclude events based on keywords or regex
- Ability to alter event properties before combining files
- Ability to specify contexts for different views of the same calendar
- Web based calendar viewer
- Install the dependencies listed in
requirements.txt
- Build a Docker image using the provided Dockerfile.
- Create a volume mapping to
/usr/src/cc/app/config
for your configuration files.
By default, the application will be accessible on port 8088.
Some configuration options can be set globally via environment variables, these are:
cc_enable_non_ics_path
: Whether to allow calendars to be accessed at https://example.com/calendar if this is set to true, calendars will be accessible at https://example.com/calendar. This should be set totrue
orfalse
and defaults tofalse
. This is included for backwards compatibility with previous versions, enabling this may cause issues if a calendar config shares it's name with a defined path.cc_enable_caching
: Whether to enable caching of the combined ics file. This should be set totrue
orfalse
and defaults tofalse
- Create a configuration file
- Place it in your mapped volume
- Make a web request to
yourserver.com/ics/configfilename
Do not include.json
in the request. Remember to include the port if the app is not behind a proxy - The CalenCraft will return a combined ics file
Each calendar configuration is a .json file that tells CalenCraft how to merge and alter your source calendars. Each file should contain a top level dictionary that contains all other configuration.
The first key in your configuration should be cc_configuration
. This set tells CalenCraft about settings that apply to the configuration file and is mandatory.
cc_configuration
should contain the following key-value pairs:
cache
: The number of minutes to cache the combined ics file for, this is optional and defaults to0
(no caching). This speeds up the response time for clients but may cause issues if your source calendars are updated frequently.allowContext
: Whether to allow context-specific configuration files to be used. This should be set totrue
orfalse
and defaults tofalse
. Setting to false will disable all contexts and a request to a context will fail.allowNoContext
: Whether to allow requests without a context to be processed. This should be set totrue
orfalse
and defaults tofalse
. If set tofalse
requests without a context will fail.defaultContext
: The name of the context to use if no context is specified in the request. The context specified here will be used for all requests without a context ifallowNoContext
is set tofalse
allowedContexts
: A list of contexts that are allowed to be used. If anoter context is specified in the request andallowNoContext
is set tofalse
anddefaultContext
is not specified the request will fail.allowWeb
: Whether to allow the ICS to be viewed online via the web interface. This should be set totrue
orfalse
and defaults tofalse
. If set totrue
the calendar will be available atyourserver.com/view/calendar
"cc_configuration": {
"cache": int,
"cacheSource": int,
"allowContext": bool,
"allowNoContext": bool,
"defaultContext": "str",
"allowedContexts": ["str", "str2", "str3"],
"allowWeb": bool
}
Each source calendar you want to merge should then be provided as a dictionary, with the key set as a name for that source (currently only used for personal reference)
source
: Each source must have a URL specified for the calendar you want to merge
"ics1name": {
"source": "https://example.com/ics1.ics"
}
You can add a datestamp to each event, this will be set to the server time that the event was processed and is useful for identifying when the event was last fetched, this is done by adding a datestamp
dictionary to the source calendar.
format
: The date/time format for the datestamp in strftime format e.g.%Y-%m-%d %H:%M:%S
template
: The datestamp string you want shown, add[[date]]
where you want the current date/time insertedposition
: Where the datestamp should be inserted (in the description). Permitted values areappend
(default) orprepend
"datestamp": {
"format": "%Y-%m-%d %H:%M:%S",
"template": "Event last updated: [[date]]",
"position": "prepend"
}
You can alter the properties of each event before they are merged, this is done by adding an alter
dictionary to the source calendar. This should contain a sub-dictionary for each property you want to alter.
alter
: This allows you to modify the properties of all events in the source calendar, this should be a dictionary containing a sub-dictionary for each property you want to modify. You may specify multiple alterations on one propertyproperty name
: The name of the property you want to modify, currently accepted values aresummary
,description
,location
, oravailability
. If altering availability see additional requirements and properties below. NB: This is the KEY of the sub-dictionary, not a property within the sub-dictionaryprepend
: A string to prepend to the selected propertyappend
: A string to append to the selected propertyreplace
: Replace the entire property with the value specified (the value may be left blank to redact that property)partReplace
: Replace a substring of the property with another string, this should be a dictionary with the following keyssearch
: The value to replacereplace
: The value to replace the search with
"alter": {
"Property Name":{
"prepend": "",
"append": "",
"replace": "",
"partReplace": {
"search": "",
"replace": ""
}
}
}
If altering availability, set the property name to availability
and include a dictionary with the following keys, both keys are optional depending on your requirements:
transp
: The transparency of the event, currently accepted values aretransparent
andopaque
. This determines whether the vent will be considered in free/busy calculations by the clientfbtype
: The type of free/busy information to provide, currently accepted values arefree
,busy
,busy-unavailable
, andbusy-tentative
. This will also set Microsoft's proprietary fields. NB: Other alter attributes are not supported within theavailability
dictionary
"availability":{
"transp": "",
"fbtype": ""
}
You can filter events before they are merged, this is done by adding an filter
dictionary to the source calendar. This should contain a sub-dictionary for each property you want to filter on, the dictionary should be named either exclude
or include
.
include
orexclude
: These allow filtering of which events to include, an include filter will only include events that meet the specified critera, while an exclude filter will remove events that meet the criteria. Both filters currently only apply an OR logic for filters of the same type. Ecludes will take priority over Includes. This dictionary should contain a sub-dictionary for each property you want to use as a filterproperty name
: The name of the property you want to check for filters, currently accepted values aresummary
,description
, andlocation
contains
: Check if the property contains the specified stringequals
: Check if the property equals the specified stringregex
: Check the property value against the specified regex
"include": {
"Property Name": {
"contains": "",
"equals": ,
"regex": ""
},
}
For each of these filter types you may specify multiple matching criteria by passing in a list "contains": ["string1", "string2"]
. For all filters, matching is case sensitive and uses OR logic.
If using contexts, you can specify different rules for each context by passing in a dictionary with the context name, and a list as the property "contains": {"context1": ["string1", "string2"], "context2": ["string1", "string3"]}
Alterations can be made to an event based on rules and criteria the event must meet, rather than a blanket alteration for all events. This is done by adding an alterRules
key to the source calendar. the alterRules
should contain a list which contains a dictionary for each rule you want to apply. Each rule should contain the following keys:
alterRules
: Allows for more complex alterations on a per-event basis. This should contain multiple sub-dictionaries with each criteria you want to match for to alterproperty
: The property you want to match, currently accepted values aresummary
,description
, andlocation
. You can also set this toall
to apply rule to all eventsmatchType
: How you want to match against the property, currently accepted values arecontains
,equals
, andregex
matchPattern
: The pattern or string to match againstalter
: The alterations to make to the events that meet the criteria above. This should use the same syntax as thealter
configurations abovecontext
: The name of a context, if set this rule will only apply to a specific context. See below for more information on contexts. Specify*
to apply to all contexts
"alterRules": [
{
"property": "",
"matchType": "",
"matchPattern": "",
"context": "",
"alter": {
}
}
]
Contexts allow the use of a single configuration with multiple views depending on who is looking at it (contexts are specified before the calendar id in the url). For example time off may show as busy if viewed from a work context, but free if viewed from a personal context.
Contexts are currently only suupported for the following parts of a configuration: alterRules
. Support for include and exclude filters will be added in a future version.
CalenCraft contains a basis calendar viewer which can be accessed by swapping /ics/
in a calendar's URL to /view/
e.g. https://yoursever.com/view/calendar
.
When using the viewer you can pass parameters in the URL to alter the view of the calendar. These are:
view
: The view to use, currently accepted values areday
,week
,month
, andagenda
. This defaults tomonth
.displayMode
: set this tokiosk
to hide the header and footer of the viewerviewDwell
: A number of seconds. If set the view will cycle through the views specified in theautoViews
parameter everyviewDwell
secondsautoViews
: A list of views to cycle through ifviewDwell
is set (seperated by-
)
https://example.com/calendar
: This format has been superceded by default, but can be enabked by setting thecc_enable_non_ics_path
environment variable totrue
. This format does not support contexts, and will be removed in a future version.https://example.com/calendar
: This format has been superceded by default, but can be enabked by setting thecc_enable_non_ics_path
environment variable totrue
. This format does not support contexts, and will be removed in a future version.https://example.com/ics/calendar
: This format is the default and will work for all configurationshttps://example.com/ics/context/calendar
: This format will only work if contexts are enabled in the configuration file and thecc_enable_contexts
environment variable is set totrue
https://example.com/ics/context/calendar
: This format will only work if contexts are enabled in the configuration file and thecc_enable_contexts
environment variable is set totrue
Some configuration options can be set globally via environment variables, these are:
CC_ENABLE_NON_ICS_PATH
: Whether to allow calendars to be accessed at https://example.com/calendar if this is set to true, calendars will be accessible at https://example.com/calendar. This should be set totrue
orfalse
and defaults tofalse
. This is included for backwards compatibility with previous versions, enabling this may cause issues if a calendar config shares it's name with a defined path.CC_ENABLE_CACHING
: Whether to enable caching of the combined ics file. This should be set totrue
orfalse
and defaults totrue
CC_BASE_URL
: The base URL for the application, this is used to generate links in the web interface. This should be set to the URL of the application e.g.https://example.com
CalenCraft currently supports basic caching of the combined ics file ON REQUESTS i.e. it currently only updates each calendar's cache when it is requested rather than on a schedule. This will work on frequently requested calendars with a longer cache time, but will mean little effect on calendars that are rarely requested. This will be improved in a future version.
- CalenCraft does not currently vaildate configuration files, if you get it wrong the program may behave unexpectedly.
- Recurring events will only include the past 10 days and future 365 days. This will become customisable in the future
- Some all day events do not render correctly
- Combine multiple ics files into one
- Alter core event properties
- Filter events
- Add datestamp to events
- Add caching
- Allow altering transparancy
- Allow altering free/busy type
- Allow adding/updating config files via web
- Add an ICS viewer
- Add ability to specify alter rules on a per-event basis
- Add env variables for configuration
- Add env variables for configuration
- Better (or any) error handling
- Allow partial replaces in alter
- Configuration generator
- Improved web interface
- Add ability to specify multiple contexts for a single calendar
- Add context support for include/exclude
- Add scheduled cache updates
- Source calendar caching
- Event Buffers
- Show transparency in viewer
- Allow customising the start and end of recurring events
- Allow altering event start and end times