trivabble/README.md

11 KiB

Trivabble

Trivabble is free a network Scrabble game under the (AGPLv3 license)[LICENSE]. It is not in any way connected to Hasbro, who has the rights on the trademark Scrabble. Trivabble provides a board, a bag full of tiles, racks and a chat. People can play without registering and join each other by using the same game number.

It features:

  • a board, a bag full of tiles, a rack for every player
  • a chat so people can communicate
  • a way to set the score of each player
  • support for different languages (set of tiles as well as the interface). Thanks to Wikipedia for providing data about tiles for each language (https://fr.wikipedia.org/wiki/Lettres_du_Scrabble)

Trivabble does not implement any rule: you are free to play your way. It does not understand what you do and is not able to compute the score, like your real board game.

Trivabble needs to be installed on a server, and is playable from a browser.

It supports:

  • latest versions of Firefox and Chromium
  • Mobile browsers on Android
  • Safari 9 and later on the iPad

It should work on any browser released after 2015, though we haven't tested it on Internet Explorer.

This documentation is intented for people who want to install Trivabble on their server. If you just want to play, head to https://trivabble.org/.

For contributions, see (contributing)[CONTRIBUTING.md].

Set up for production

Note: Please be aware that this is alpha-quality software. We do our best to avoid breaking stuff but we might from time to time. With this out of the way…

Trivabble is composed of two parts: the server and the client.

  • The server is a Javascript program that runs on Node JS. It waits for HTTP and WebSocket requests on a configurable port (default: 3000), and a configurable address (default: localhost). This server needs to run for Trivabble to work, and proxified through a Web server like Apache or Nginx.
  • The client is a set of static files that need to be server by a Web server

Prerequisite

You need to have:

  • Node (version 10 or later)
  • make
  • git
  • a Web server such as Apache or Nginx.

On a Debian-based system, the following command will install make and node:

apt install make nodejs git

On some systems, the node binary does not exist and is called nodejs instead. Trivabble expects the Node binary to be node. On these systems, a nodejs-legacy package may exist to fix this. Otherwise, you will need to create a symblink.

As for the web server, we will asume that you already have one running and correctly configured.

Installation

We will assume www-data is the UNIX user of your Web server. Adapt if necessary.

  1. Set up the directories that will host the server and the client. Create a UNIX user for the Trivabble server and set the right permission: The server should be outside the root of your Web server. The client will be served by your Web server.

    Let's store the chosen paths in environment variables (adapt if necessary) and create these directories:

    export TRIVABBLE_SERVER_PATH=/opt/trivabble-server
    export TRIVABBLE_PUBLIC_PATH=/var/www/html/trivabble
    
    sudo groupadd trivabble
    sudo useradd -G trivabble trivabble
    sudo mkdir -p "$TRIVABBLE_PUBLIC_PATH"
    sudo chown www-data:www-data "$TRIVABBLE_PUBLIC_PATH"
    sudo chmod g+x "$TRIVABBLE_PUBLIC_PATH"
    sudo mkdir -p "$TRIVABBLE_SERVER_PATH"
    sudo chown trivabble:trivabble "$TRIVABBLE_PUBLIC_PATH"
    
  2. Clone the repository somewhere (in your HOME directory for instance):

    git clone https://gitlab.com/raphj/trivabble.git
    cd trivabble
    
  3. Get the latest production version:

    git checkout "$(git tag --list '[prod]*' --sort=v:refname | tail -1)"
    
  4. Make sure you still have your environment variable set (adapt if necessary):

    export TRIVABBLE_SERVER_PATH=/opt/trivabble-server
    export TRIVABBLE_PUBLIC_PATH=/var/www/html/trivabble
    

    Also make sure you still are in the trivabble repository.

  5. Run, as a user having sudo privileges:

    ./bin/upgrade-prod.sh --prod-public-dir "$TRIVABBLE_PUBLIC_PATH" --prod-server-dir "$TRIVABBLE_SERVER_PATH" --trivabble-chown trivabble:trivabble --webserver-chown www-data:www-data
    

    This will:

    • run make so everything that needs to be build will be built, including the language files
    • transform Javascript files so they are compatible with older browsers
    • copy the server and client files to the chosen folders
  6. (Optional) - In the public directory ($TRIVABBLE_PUBLIC_PATH), review config.js.sample. If there are values you would like to change, copy it to config.js and make the desired changes.

  7. Run the Trivabble server.

    cd "$TRIVABBLE_SERVER_PATH"
    node trivabble-server
    

    You may want to run this in a screen so you can leave the session and trivabble-server still runs in the background.

    Better yet, create a service for your init system:

    • create /usr/local/bin/start-trivabble:

      #!/bin/sh
      cd /var/www/html/raph/raw/trivabble
      exec sudo -u www-data DEBUG_LOG=true nodejs trivabble-server.js
      
  8. Configure your web server.

Content-Security Policy Header

Trivabble loads 5 static javascript files, 2 static css files and a sound from its origin, and connects to the same server by SSE or websockets. Here is the recommended HTTP CSP header for Trivabble:

Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; connect-src 'self'; media-src 'self'

We advise you to set this up to improve the security of your setup.

In the next two sections, we describe the configuration for Apache 2 and Nginx.

Apache 2

On Apache 2, the relevant rules are:

RewriteEngine on
RewriteRule "^/?:trivabble/ws/(.*)" ws://localhost:3000/ws/$1 [P]

ProxyPass "/:trivabble" http://localhost:3000/ retry=0
ProxyPassReverse "/:trivabble" http://localhost:3000/

You will need to enable modules proxy_http, proxy_wstunnel (if you do not disable websockets in config.js) and rewrite:

a2enmod proxy_http
a2enmod proxy_wstunnel
a2enmod rewrite

⚠️ Be careful to allow enough concurrent processes / threads / workers on your web server. Each player requires one long-standing connection (XHR, SSE or WebSocket), plus small requests when not using WebSockets. Long-standing connections may cause issues with Apache 2, and using HTTP 2 may lead to "interesting" behavior.

Nginx

Here is an example of an Nginx configuration for Trivabble:

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        server_name trivabble.example.org;

        location /:trivabble/ws/ {
                proxy_pass http://127.0.0.1:3000;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";
                proxy_set_header Host $host;
        }

        location /:trivabble {
                proxy_pass http://127.0.0.1:3000;
                proxy_buffering off;
        }

        location /trivabble {
                alias /var/www/html/trivabble-public;
        }

	# SSL configuration here
}

Enable the spell checker

The process of building the dictionaries takes a lot of disk space and require huge amount of memory (around 1GB).

Install wget and aspell (to have the word-list-compress command), and run:

cd dict-dists-extractor
make

If you want to limit spelling to a subset of languages, you can define the list by the LANGS variable before executing the make command such as:

cd dict-dists-extractor
LANGS="de en fr" make

This way, you only build English, French and German dictionaries.

To deactivate spell checker at system level, you need to empty dictionary list contained into file public/dict/list.js. Such command can be used:

echo > public/dict/list.js

Technical appendices

Board extractor

Wikipedia provides tile distributions (content of the bag and points) for various languages. Board languages are built from a Wikipedia page.

General parsing

Most board languages are extracted from the French version of the Wikipedia page which has a simple document structure. Parsing is done by a JS script named make_board.js:

  • each new language board is proceeded by a level 2 header containing language name,
  • tile points is followed by point(s)
  • tile letter and number of tiles are easy extracted by a regex which looks like <b>(letter)</b> <small>x(times)</small>

Special languages

Some languages are only defined into the English version. So we copy them into separated text files and parsing is done by an AWK named make_board.awk.

Dictionary building process

The spell checker in Trivabble is based on Aspell dictionaries. However, as Trivabble only uses a subset of letters (most accentuated characters have to be replaced by standard ones), we can't use Aspell engine straightforward; we need to build lists of words that only use playable characters.

Overall concept

In order to build dictionaries for various languages, we first need to retrieve Aspell dictionary lists. Then we retrieve the last versions of dictionaries for every languages and we build them. Thanks to two Aspell commands, we build the full list of words. Based on the distribution of tiles, we translate every derived (most of the time accentuated) character by the appropriate one, and finally we remove duplicated entries.

Details on Makefile rules

Rule '$(OBJ_DIR)/src.mk' retrieves on Aspell site the last version of the dictionary list, extract dictionary archive URL and build a sub-makefile with rules to retrieve every needed dictionary.

Rule '%.dir' unpacks dictionary archives and build Aspell dictionary. Result directory is rename as LANG.dir

Rule '%.low' expands a Aspell dictionary into a list of words (low means "List Of Words"". Phrases are split into words. Finally the list is ordered and clean from duplicated words.

Rule '$(ROOT_DICT)/%.dict':

  • excludes words with numbers, dashes, apostrophes and other forbidden signs,
  • translates accentuated characters into standard ones,
  • up-case all words,
  • and remove duplicated words. This file can be used by Trivabble for spell checking.

Last rule 'check-%' checks that file %.dict contains only words with characters base on language tile bag.

Remarks

Some lists of words are too huge (for example Hungarian or Turkish are agglutinative languages), so Trivabble will not be able to check spelling for those languages.

Some languages don't have any Aspell dictionary.

Credits

Thanks Laurent Mazet for many contributions. Thanks Ysabeau for the design of the bag. Thanks every other past and future contributors who have written code, tickets, tested the game and who I have not mentionned here yet (please tell me if your name is missing!).