Gischat API backend for chatting with your tribe in GIS tools.
No database : messages are not stored. Just stateless websockets.
Here are the known clients implementing gischat / QChat, at the moment:
- QChat QGIS plugin, available from the official QGIS plugin repository.
- QField plugin.
And other to come!
Following instances are up and running :
| URL | Description | Location |
|---|---|---|
| https://qchat.geotribu.net | Geotribu's official instance | Germany |
- Channel can be fetched using the
/channelsendpoint - Rules can be fetched using the
/rulesendpoint - Number of connected users can be fetched using the
/statusendpoint - List of connected and registered users can be fetched using the
/channel/{channel}/usersendpoint - New users must connect a websocket to the
/channel/{channel}/wsendpoint - After connecting to the websocket, it is possible to register the user in the channel by sending a
newcomermessage (see below) - Messages passing through the websocket are strings with a JSON structure, they have a
typekey which represent which kind of message it is
Those are the messages that might transit through the websocket.
Each of them has a "type" key based on which it is possible to parse them :
-
"text": basic text message send by someone in the channel, e.g.:{ "type": "text", "author": "jane_doe", "avatar": "mGeoPackage.svg", "text": "Hi @all how are you doing ?" }"author"value must be alphanumeric (or_or-) and have min / max length set byMIN_AUTHOR_LENGTH/MAX_AUTHOR_LENGTHenvironment variables
avatarvalue is optional and usually points to a QGIS resource icon (see the ones available in the QChat/QTribu plugin)
"text"value must have max length set byMAX_MESSAGE_LENGTHenvironment variable -
"image": image message send by someone in the channel, e.g.:{ "type": "image", "author": "jane_doe", "avatar": "mIconPostgis.svg", "image_data": "utf-8 string of the image encoded in base64" }The image will be resized by the backend before broadcast, using the
MAX_IMAGE_SIZEenvironment variable value -
"nb_users": notifies about the number of users connected to the channel, e.g.:{ "type": "nb_users", "nb_users": 36 } -
"newcomer": someone has just registered in the channel, e.g.:{ "type": "newcomer", "newcomer": "jane_doe" }After having connected to the websocket, it is possible to register a user by sending a
newcomermessage -
"exiter": someone registered has left the channel, e.g.:{ "type": "exiter", "exiter": "jane_doe" } -
"like": someone has liked a message, e.g.:{ "type": "like", "liker_author": "john_doe", "liked_author": "jane_doe", "message": "Hi @john_doe how are you doing ?" }means that
john_doelikedjane_doe's message ("Hi @john_doe how are you doing ?")The messages of the
liketype are sent only to the liked author, if this user is registered. If this user is not registered, it won't be notified -
"geojson": someone shared a geojson layer, e.g.:{ "type": "geojson", "author": "jane_doe", "avatar": "mIconPostgis.svg", "layer_name": "my_geojson_layer", "crs_wkt": 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]', "crs_authid": "EPSG:4326", "geojson": { "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "attribute_1": "something" }, "geometry": { "type": "Point", "coordinates": [ 1, 2 ] } }, ... ] } }The coordinates of the
geojsonfeatures must be expressed using the providedcrs_wktandcrs_authid -
"crs": someone shared a CRS, e.g.:{ "type": "geojson", "author": "jane_doe", "avatar": "mIconPostgis.svg", "crs_wkt": 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]', "crs_authid": "EPSG:4326", } -
"bbox": someone shared a bbox, e.g.:{ "type": "bbox", "author": "jane_doe", "avatar": "mIconPostgis.svg", "crs_wkt": 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]', "crs_authid": "EPSG:4326", "xmin": -1.1, "xmax": 1.1, "ymin": -1.1, "ymax": 1.1 } -
"position": someone shared a position, e.g.:{ "type": "bbox", "author": "jane_doe", "avatar": "mIconPostgis.svg", "crs_wkt": 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]', "crs_authid": "EPSG:4326", "x": 1.234, "y": 5.678 } -
"uncompliant": someone sent an uncompliant message and the server answers with such a message, e.g.:{ "type": "uncompliant", "reason": "Too many geojson features : 600 vs max 500 allowed" }This example is the server response if sending a
ŋeojsonmessage with too many features
Note
NB_UVICORN_WORKERS refers to the number of async workers. A usual convenient value would be : (nb_cpu * 2) + 1.
CHANNELS environment variable is a comma-separated list of strings which represent the available chat channels.
RULES environment variable describes the instance's rules. Useful information that users should know, even when skimming content.
MAX_IMAGE_SIZE environment variable describes the max size of image in pixels. The server will resize images based on this value.
MAX_GEOJSON_FEATURES environment variable describes the max number of features allowed in a geojson message. If there is more feature, the message will not be considered and the server will respond with a uncompliant message.
-
Install
dockerusing the official documentation -
Create a
docker-compose.yamlfile on your server:services: api: image: gounux/gischat:latest container_name: gischat-app environment: - NB_UVICORN_WORKERS=5 - CHANNELS=QGIS,Field and mobile,GIS tribe,Kitchen,Garden - RULES=Be kind and nice to this wonderful world - MAIN_LANG=en - INSTANCE_ID=abcdefghijklmnopqrstuvwxyz - ENVIRONMENT=production - MIN_AUTHOR_LENGTH=3 - MAX_AUTHOR_LENGTH=32 - MAX_MESSAGE_LENGTH=255 - MAX_IMAGE_SIZE=800 - MAX_GEOJSON_FEATURES=500 - MAX_STORED_MESSAGES=5 - REDIS_HOST=redis ports: - 8000:8000 restart: unless-stopped redis: image: redis:latest container_name: gischat-redis restart: unless-stopped volumes: - redis-data:/data volumes: redis-data: -
Launch the app using
compose:docker compose up -d
-
Have a look at the logs:
docker compose logs -f
-
Install nginx and certbot:
apt install nginx certbot
-
Get a Let's Encrypt SSL certificate for your domain:
# stop nginx service systemctl stop nginx # get the certificate certbot certonly --standalone -d DOMAIN # restart nginx service systemctl start nginx
The Let's Encrypt SSL certificate should be saved to
/etc/letsencrypt/live/DOMAIN -
Create a nginx config file:
touch /etc/nginx/sites-available/gischat.conf
-
Edit the file and add the following content (using your domain):
upstream gischat_upstream { server 127.0.0.1:8000; } server { listen 80; server_name <DOMAIN>; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name <DOMAIN>; ssl_certificate /etc/letsencrypt/live/<DOMAIN>/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/<DOMAIN>/privkey.pem; location / { proxy_pass http://gischat_upstream; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 86400; } }
-
Create a symlink to enable the nginx config file :
ln -s /etc/nginx/sites-available/gischat.conf /etc/nginx/sites-enabled/gischat.conf
-
Check that the nginx config file is okey :
nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful -
Reload nginx configuration
systemctl reload nginx
That's it, you should be able to chat now with your fellow GIS mates !
- Install poetry:
python -m pip install poetry- Install
redison your local machine:
sudo apt install redis-server- Install project's dependencies using poetry:
poetry install- Install pre-commit tools:
poetry run pre-commit install- Create local environment file and edit it:
cp .env.example .env- Launch API:
poetry run uvicorn gischat.app:app --reload --env-file .env --log-config=log_config.yaml- Build docker image:
docker build . --tag geotribu/gischat:latest- Run docker image:
docker run --env CHANNELS=QGIS,QField,Geotribu --env RULES="Those are the rules: ..." geotribu/gischat:latest-
Install dev dependencies:
poetry install --with=dev
-
Run unit tests:
poetry run pytest tests