HighScore: The Open-Source Leaderboard Solution for Indie Game Developers
Tags: typescript, webdev, programming, opensource
Published: 2022-12-14 14:00:00

## Highscore v0.3.0

The last week I worked on my open-source project [HighScore](https://github.com/EmilienLeroy/HighScore) and I released a new version. HighScore is an open-source leaderboard and is an alternative to the Google Play Service, which allows you to create leaderboards for your games and add some others features to your game. Highscore is currently under development and a lot of features are missing, but you can try the leaderboards which allow you to store your game score easily. This new version contains a new bad words filter, a custom download link and a rate limit to prevent spam.

## Filter bad words

This new feature allows you to prevent poorly words into the name of the score sent. To work I use this [bad-words](https://github.com/web-mech/badwords) library which already contains a default list of words. However, you can also add your own words depending on your language.

![Bad words](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ti7xtnpa4xqz2p8u6gsn.gif)

For HighScore, I just created a middleware that cleans each request which contains the name field into his body. This is the sample of the middleware.

```ts
import { MiddlewareMethods, Middleware } from "@tsed/platform-middlewares";
import { Context, Next } from "@tsed/common";
import { words } from '../../config/ban.json';
import { envs } from "../config/envs";
import BadWordsFilter from "bad-words";

@Middleware()
export class ScoreMiddleware implements MiddlewareMethods {
	private filter: BadWordsFilter;
	
	constructor() {
		const { HIGHSCORE_DISABLE_BAD_WORDS } = envs;
		// Configure the bad word filter on the app start
		this.filter = new BadWordsFilter({
			emptyList: HIGHSCORE_DISABLE_BAD_WORDS === 'true'
		});

		// Add more custom words from 'config/ban.json'
		this.filter.addWords(...words);
	}


	use(@Context() $ctx: Context, @Next() next: Next) {
	    // Prevent request without body
		if (!$ctx.request.body) {
			return next();
		}

		// Clean body name
		const { name } = $ctx.request.body;
		$ctx.request.body.name = this.filter.clean(name);
		return next();
	}
}
```

> I use Ts.ed as framework, go to [this site](https://tsed.io/) to known more about this awesome framework.


## Custom download link

The second feature of this release is the custom download link. This allows you to redirect to another page depending on the user platform. Why this feature? Because when you create a game for multiple platforms like Android, iOS, Windows, and Linux. You want to have a single entry point to download your app or game. For example, if you want to create a Qr code for your mobile game that is for Android and iOS you can use this endpoint in your QR code. When the QR code is scanned the user is redirected to the good application store.

![Download](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n4tgj18tx41y9kflxfhg.gif)

## Rate limit to prevent spam

The last feature is a rate limit to prevent spam. Highscore has no auth system all endpoints are public and can be accessible by anybody. That's why adding a rate limit is useful to prevent abuse requests for a malicious users. For this, I used the very good [express-rate-limit](https://github.com/express-rate-limit/express-rate-limit) library which does the job perfectly. Like all other features, you can configure the rate limit using env variables.

![Rate limit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t07jcz8xvymkhkrgojd7.gif)

## What's next

The next release will contain a custom privacy page pre-built for the application store, like Google Play or the AppStore. It will also contain a new category system to create a leaderboard for different categories. You can already try HighScore using the official [docker image](https://hub.docker.com/r/emilienleroy/highscore) or contribute to it via the [GitHub repository](https://github.com/EmilienLeroy/HighScore).

Thank you for reading this article!