first commit
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018 Jeff MrBear
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
|
||||||
|
# gitlab-ldap-sync
|
||||||
|
|
||||||
|
Python project to sync ics calendars into nextcloud.
|
||||||
|
|
||||||
|
Adapted from https://github.com/buzz/ics2owncloud.py .
|
||||||
|
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
This project has been tested on CentOS 7.6 with nextcloud 14.x, google calendar and zimbra calendar.
|
||||||
|
|
||||||
|
```
|
||||||
|
Python : 3.4.9
|
||||||
|
pip3 : 8.1.2
|
||||||
|
requests : 2.9.1
|
||||||
|
icalendar : 3.9.2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Installing
|
||||||
|
|
||||||
|
You could either install requirements system wide or use virtual environment / conda, choose your poison.
|
||||||
|
|
||||||
|
To get this up and running you just need to do the following :
|
||||||
|
|
||||||
|
* Clone the repo
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/MrBE4R/nextcloud_ics_sync.git
|
||||||
|
```
|
||||||
|
* Install requirements
|
||||||
|
```bash
|
||||||
|
pip3 install -r ./nextcloud_ics_sync/requirements.txt
|
||||||
|
```
|
||||||
|
* Edit config.json with you values
|
||||||
|
```bash
|
||||||
|
cp nextcloud_ics_sync/nextcloud_ics_sync.ini{.example,}
|
||||||
|
EDITOR ./nextcloud_ics_sync/nextcloud_ics_sync.ini
|
||||||
|
```
|
||||||
|
* Start the script and enjoy your calendars being synced
|
||||||
|
```bash
|
||||||
|
cd ./nextcloud_ics_sync && ./nextcloud_ics_sync.py
|
||||||
|
```
|
||||||
|
|
||||||
|
You should get something like this :
|
||||||
|
```bash
|
||||||
|
Imported: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (204)
|
||||||
|
Imported: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (204)
|
||||||
|
Imported: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (204)
|
||||||
|
Imported: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (204)
|
||||||
|
Imported: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx@gmail.com (204)
|
||||||
|
Imported: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx@gmail.com (204)
|
||||||
|
Imported: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx@gmail.com (204)
|
||||||
|
Imported: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx@gmail.com (204)
|
||||||
|
```
|
||||||
|
|
||||||
|
You could add the script in a cron to run it periodically.
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
How to configure config.json
|
||||||
|
```ini
|
||||||
|
[DEFAULT] # The nextcloud server where we will sync all calendar
|
||||||
|
username: username # Nextcloud username
|
||||||
|
password: password # Nextcloud password
|
||||||
|
server: https://nextcloud.example.com/ # Nextcloud URL
|
||||||
|
|
||||||
|
[import_a] # a convenient name for you
|
||||||
|
calendar: calendar_xy # name of the calendar in nextcloud. must exist prior sync
|
||||||
|
ics_url: https://cloud.owncloud.org/index.php/apps/calendar/export.php?calid=6 # url to the ics file
|
||||||
|
ics_username : # username of the distant ics server
|
||||||
|
ics_password : # password of the distant ics server
|
||||||
|
|
||||||
|
[import_b]
|
||||||
|
calendar: zimbra
|
||||||
|
ics_url: https://zimbra.example.com/home/username/Calendar?fmt=ics
|
||||||
|
ics_username :
|
||||||
|
ics_password :
|
||||||
|
|
||||||
|
[import_c]
|
||||||
|
calendar: google
|
||||||
|
ics_url: https://calendar.google.com/calendar/ical/username/private-xxxxxxx/basic.ics
|
||||||
|
ics_username :
|
||||||
|
ics_password :
|
||||||
|
```
|
||||||
|
For now ```ics_username``` and ```ics_password``` are mandatory in each import, meaning the keys should be here but empty if not needed by the distant ics server.
|
||||||
|
|
||||||
|
```create_user``` If set to true, the script will create the users in gitlab and add them in the corresponding groups. Be aware that gitlab will send a mail to every new users created.
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- [ ] validate if ```ics_username``` and ```ics_password``` are in config to avoid putting empty value in config
|
||||||
|
- [ ] your suggestions
|
||||||
|
## Built With
|
||||||
|
|
||||||
|
* [Python](https://www.python.org/)
|
||||||
|
* [icalendar](https://icalendar.readthedocs.io/en/latest/)
|
||||||
|
* [requests](http://docs.python-requests.org/en/latest/)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Please read [CONTRIBUTING.md](https://gist.github.com/PurpleBooth/b24679402957c63ec426) for details on our code of conduct, and the process for submitting pull requests to us.
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
* **Jean-François GUILLAUME (Jeff MrBear)** - *Initial work* - [MrBE4R](https://github.com/MrBE4R)
|
||||||
|
|
||||||
|
See also the list of [contributors](https://github.com/MrBE4R/nextcloud_ics_sync/contributors) who participated in this project.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
|
||||||
|
|
||||||
|
## Acknowledgments
|
||||||
|
|
||||||
|
* Hat tip to anyone whose code was used
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
username: username
|
||||||
|
password: password
|
||||||
|
server: https://nextcloud.example.com/
|
||||||
|
|
||||||
|
[import_a]
|
||||||
|
calendar: calendar_xy
|
||||||
|
ics_url: https://nextcloud.example.org/index.php/apps/calendar/export.php?calid=6
|
||||||
|
ics_username :
|
||||||
|
ics_password :
|
||||||
Executable
+85
@@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import configparser, logging, requests, traceback
|
||||||
|
from icalendar.cal import Calendar
|
||||||
|
|
||||||
|
log_option = {
|
||||||
|
'format': '[%(asctime)s] [%(levelname)s] %(message)s',
|
||||||
|
'level': getattr(logging, 'INFO')
|
||||||
|
}
|
||||||
|
logging.basicConfig(**log_option)
|
||||||
|
logging.getLogger("requests").setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
CALDAVURL = '%sremote.php/dav/calendars/%s/%s'
|
||||||
|
|
||||||
|
|
||||||
|
def do_import(username, password, calendar, server, ics_url, ics_username, ics_password):
|
||||||
|
logging.info(' Working with calendar %s...' % calendar)
|
||||||
|
base_url = CALDAVURL % (server, username, calendar)
|
||||||
|
|
||||||
|
target_fetch_url = '%s?export' % base_url
|
||||||
|
r = requests.get(target_fetch_url, auth=(username, password))
|
||||||
|
r.raise_for_status()
|
||||||
|
try:
|
||||||
|
target_cal = Calendar.from_ical(r.text)
|
||||||
|
except ValueError as e:
|
||||||
|
logging.error(' Warning: Could not parse iCal (%s)' % target_fetch_url)
|
||||||
|
logging.error(e)
|
||||||
|
return
|
||||||
|
|
||||||
|
existing_uids = [e['UID'].to_ical() for e in target_cal.walk('VEVENT')]
|
||||||
|
|
||||||
|
sourceRequest = requests.get(ics_url, auth=(ics_username, ics_password))
|
||||||
|
sourceRequest.encoding = 'utf-8'
|
||||||
|
sourceContent = sourceRequest.text
|
||||||
|
c = Calendar.from_ical(sourceContent)
|
||||||
|
|
||||||
|
imported_uids = []
|
||||||
|
for e in c.walk('VEVENT'):
|
||||||
|
uid = bytes.decode(e['UID'].to_ical())
|
||||||
|
uid.replace('\'', '')
|
||||||
|
uid.replace('/', 'slash')
|
||||||
|
name = bytes.decode(e['SUMMARY'].to_ical())
|
||||||
|
cal = Calendar()
|
||||||
|
cal.add_component(e)
|
||||||
|
r = requests.put('%s/%s.ics' % (base_url, uid),
|
||||||
|
data=cal.to_ical(),
|
||||||
|
auth=(username, password),
|
||||||
|
headers={'content-type': 'text/calendar; charset=UTF-8'}
|
||||||
|
)
|
||||||
|
if r.status_code == 500 and r'Sabre\VObject\Recur\NoInstancesException' in r.text:
|
||||||
|
logging.warning(' No valid instances: %s (%s)' % (uid, name))
|
||||||
|
elif r.status_code == 201 or r.status_code == 204:
|
||||||
|
logging.info(' Imported: %s (%s)' % (uid, name))
|
||||||
|
imported_uids.append(uid)
|
||||||
|
else:
|
||||||
|
r.raise_for_status()
|
||||||
|
|
||||||
|
for uid in existing_uids:
|
||||||
|
if not uid in imported_uids:
|
||||||
|
r = requests.delete('%s/%s.ics' % (base_url, uid), auth=(username, password))
|
||||||
|
if r.status_code == 204:
|
||||||
|
logging.info('Deleted %s (%s)' % (uid, name))
|
||||||
|
elif r.status_code == 404:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
r.raise_for_status()
|
||||||
|
logging.info(' Done.')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
logging.info('Initializing script...')
|
||||||
|
Config = configparser.RawConfigParser()
|
||||||
|
Config.read('nextcloud_ics_sync.ini')
|
||||||
|
logging.info('Done.')
|
||||||
|
logging.info('Importing calendars...')
|
||||||
|
for key in Config.sections():
|
||||||
|
logging.info(' Working on section %s' % key)
|
||||||
|
try:
|
||||||
|
do_import(
|
||||||
|
Config.get(key, 'username'), Config.get(key, 'password'), Config.get(key, 'calendar'), Config.get(key, 'server'),
|
||||||
|
Config.get(key, 'ics_url'), Config.get(key, 'ics_username'), Config.get(key, 'ics_password')
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(traceback.print_exc())
|
||||||
|
logging.info(' Done.')
|
||||||
|
logging.info('Done.')
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
requests==2.9.1
|
||||||
|
icalendar==3.9.2
|
||||||
Reference in New Issue
Block a user