Synchronise events from Google Calendar to user profile in Slack
This project is my test ground for learning Rust language. The goal is as follows:
- get google calendar events on a predetermined interval
- using configuration mapping google calendar event title to slack user profile settings set the new value for slack user profile
Assuming linux Ubuntu as OS or WSL2 with Ubuntu.
- clone the repo to your local machine
- install rust language
- open terminal in root of the project
- install pre-commit tool:
sudo apt update && sudo apt install -y pre-commit
- install pre-commit hook for the project:
pre-commit install
- run tests for entire project:
cargo test --workspace
- build entire project (in debug, unoptimised mode), check
target/debug
:
cargo build --workspace
- build entire project (optimised for production), check
target/release
:
cargo build --release --workspace
- Run
slack-gcal-sync --help
to see command line interface options.
The application configuration is read in the following order:
- if
--application-config-path
cli option is specified, we try to load it from ajson
file at that path. The application configuration must specify all values for application configuration, or it will fail to load. - if
--application-config-path
cli option is not specified, a default application path will be used:config/application_config.json
. - if there is no application config file (at default or specified path) we will set default app config.
- any CLI options such as
--calendar-id
override what is specified in the application config file or default application config.
This file holds application configuration in json format. All keys are required for configuration to be valid.
{
"calendar_id": "[email protected]",
"service_account_key_path": ".secrets/.service_account.json"
}
In the following 2 sections you will see how to set up your Slack and Google Cloud Platform to get necessary credentials and set up access permissions for slack-gcal-sync app to work.
- navigate to Slack API new app page: https://api.slack.com/apps?new_app=1
- Click
Create New App
- Click
From a Manifest
- select target workspace for the new app and click
Next
- Paste this manifest in the
Json
tab to allow user profile reading and writing (only) and clickNext
{
"display_information": {
"name": "user-profile-app",
"description": "User Profile Integration",
"background_color": "#004492"
},
"oauth_config": {
"scopes": {
"user": [
"users.profile:read",
"users.profile:write"
]
}
},
"settings": {
"org_deploy_enabled": false,
"socket_mode_enabled": false,
"token_rotation_enabled": false
}
}
- click
Create
- After your app is created, navigate to
Settings -> Install App
to install it in your workspace and generate necessaryOAuth tokens
for programmatic communication.
- Click
Install to <your workspace name>
(here my workspace is calledlab
so it shows asInstall to lab
). - Confirm that you want to install the app and click
Allow
.
- After you click
Allow
you will be presented with theUser OAuth Token
which will be used for programmatic communication with Slack API on behalf of your user. The secret always starts withxoxp
.
- This can also be found in
Features -> OAuth & Permissions
.
-
if you already have google account you can just join google cloud platform, otherwise create a new google account.
-
set up Google Cloud Account - you can select the free trial.
-
Click
Select a project
to use existing or create a new one.
- Click
NEW PROJECT
(we assume starting from scratch here).
- Give your project a name and click
CREATE
.
- You will see a notification popup, click
SELECT PROJECT
.
- Click on hamburger navigation menu.
- Click on
APIs & Services
->Library
tab.
- Scroll down a bit to
Google Workspace
group of apis or just click on it in the sidebar menu and click onGoogle Calendar API
box.
- Click
ENABLE
to switch Google Calendar API in your project.
-
Now we need to create a service account to allow machine to machine communication without need for interactive login.
-
In the view that appears after you enabled Google Calendar API, click
Credentials
in the sidebar.
- Click
+ CREATE CREDENTIALS
.
- Click
Service account
.
- Fill in
Service account name
and optionallyService account description
and clickDONE
since we don't need to grant any optional permissions here.
- Click on your newly listed service account to add a service account key.
- Make note of the auto-generated email - we will need it to share Google Calendar with this service account.
- Click on
KEYS
tab.
- Click on
Add KEY
->Create new key
.
- In the popup use the default
JSON
key type and clickCREATE
.
- The private key in json format will be saved in your
downloads
folder on your machine - keep it safe. - This json file is needed by slack-gcal-sync app to authenticate itself to google calendar api. You will need to specify path to it in the app configuration.
- open Google Calendar for your Google account
- Click on the cog drop down and
Settings
- in
Settings for my calendars
click on the calendar you want to share with the service account
- Scroll down to
Share with specific people or groups
and clickAdd people and groups
- Fill in the auto-generated email that your service account got from a step above and select appropriate access level. For
read only
useSee all event details
.
- Click
Send
- The calendar id is needed when making calls to Google calendar API and needs to be set in the slack-gcal-sync app configuration.
- Simply scroll down on the selected calendar settings page to
Integrate calendar
section and copyCalendar ID
.
To see what mockito server is being called with:
- add
env_logger
to dev dependencies - set up logger at the beginning of test:
let _ = env_logger::try_init();
- run test configuration with environment variable set
RUST_LOG=mockito=debug
- mockito server will nicely show what it was called with like this:
[2024-12-31T17:42:11Z DEBUG mockito::server] Request received:
GET /calendars/test_calendar_id/events?timeMin=2024-12-31T00%3A00%3A00.000Z&timeMax=2025-01-01T00%3A00%3A00.000Z&alt=json
user-agent: google-api-rust-client/6.0.0
authorization: Bearer <REDACTED>
content-length: 0
host: 127.0.0.1:33285