FiveM script makers who upload their content to GTAPoliceMods can take advantage of our GPM Integrations platform to notify users quickly and effortlessly of new updates. This guide shows how to set up such a system with FiveM's CLR (C#) environment.
Our goal is to check for new updates every time the resource starts, and notify server owners when they're running an out-of-date version. Using GPM Integrations, we can do this at no cost. We'll be using Ray Designs Development Modification Studios INC LLC's "Who's Joe?" as our example today.
The first step is to create a GPM Integration. Heading over to https://gtapolicemods.com/integrations/new/, we can enter a name and quick description for our app. Being detailed helps GPM to know how their systems are being used and how they can be improved. Leave the default "Access Type" selected.
We've created our Integration. GPM knows us now, and they've given us a key to send with our version checks. Head over to the "API Access" page on the sidebar to get the key.
The resulting page will show you your API Key, and not much else. This key is specific to you. Note it down for later, or remember this page so you can come back and find it.
That's everything we need to do on the GPM side. Our Integration is authorized and ready to go. Let's hop over to "Who's Joe" and get started on our FiveM script code. This guide is working off of the assumption that your script already is created (and works).
Here's a peek at the server-side code for "Who's Joe" and its version checks:
using System.Net.Http; using CitizenFX.Core; namespace WhosJoe.Server { public class ServerMain : BaseScript { // The "Who's Joe" GPM Downloads ID private static readonly int GpmDownloadsId = 808; // The current version of "Who's Joe?" private static readonly string CurrentVersion = "1.2.5"; // Our GPM API Key private static readonly string GpmApiKey = "sas5osekvwqpdosozsiuyhlaw1iuux"; // Our HttpClient private static readonly HttpClient client = new HttpClient(); public ServerMain() { Debug.WriteLine("Joe Who?"); // Disable certificate validation // CAUTION: This could be dangerous. We're only using the response we // receive to send a small message, and we're very careful about how // we do it. FiveM can't validate GPM's certificates on its own. System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; // Add our API Key to the request client.DefaultRequestHeaders.Add("X-GPM-Key", GpmApiKey); // Run the update check CheckForUpdates(); } private async void CheckForUpdates() { try { // Send our request to GPM var response = await client.GetAsync($"https://gtapolicemods.com/dev/downloads/latest?id={GpmDownloadsId}"); // Makes sure we got a valid response back response.EnsureSuccessStatusCode(); // Checks that the version we're running IS NOT the newest version if (!CurrentVersion.Equals(await response.Content.ReadAsStringAsync())) { Debug.WriteLine("A new version of Who's Joe is available on GPM!"); } } catch (HttpRequestException) { // Our request failed, print a short message Debug.WriteLine("Couldn't check for Who's Joe updates!"); } } } }
There's a lot to unpack here. Let's take a look at this chunk-by-chunk.
// The "Who's Joe" GPM Downloads ID private static readonly int GpmDownloadsId = 808; // The current version of "Who's Joe?" private static readonly string CurrentVersion = "1.2.5"; // Our GPM API Key private static readonly string GpmApiKey = "sas5osekvwqpdosozsiuyhlaw1iuux"; // Our HttpClient private static readonly HttpClient client = new HttpClient();
We've created four member fields here. Three of them are simply holding pieces of information about our Integration and our script. "GpmDownloadsId" is the ID of the upload we're checking, which you can find in the URL of your upload. (In this case, we got it from https://gtapolicemods.com/files/file/808-whos-joe/). "CurrentVersion" is the version of the running script, and is what we compare against when we're checking for updates. Remember to update this every release if you use a similar system! "GpmApiKey" is the key we found in the Developers Center. Make sure you replace this one with your own key.
The third field, "client", holds our HttpClient. This is the C# class which allows us to make requests to GPM. Make sure to import "System.Net.Http". Moving on...
// Disable certificate validation // CAUTION: This could be dangerous. We're only using the response we // receive to send a small message, and we're very careful about how // we do it. FiveM can't validate GPM's certificates on its own. System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; // Add our API Key to the request client.DefaultRequestHeaders.Add("X-GPM-Key", GpmApiKey); // Run the update check CheckForUpdates();
This section of code may look a little daunting at first, no-thanks to the "CAUTION" message I've added. Removing the line beginning with "System.Net.ServicePointManager" and running the script will result in an error, as the FiveM server can't validate TLS certs, A.K.A., it can't verify that our request is actually going to GPM. This isn't a big problem for us, being that we're only using the response to write a message to the console. The line above simply tells the server to disregard verifying GPM's certs. If you use the Integrations API for something more sensitive, consider adding more protections.
We're also telling the HttpClient we created earlier to add our API Key to every request. Make sure to swap in your own API Key from the Developers Center.
Lastly, we're running our CheckForUpdates method, which handles the actual update check. We don't just check for updates in the Main method because we want to run code in the background.
private async void CheckForUpdates() { try { // Send our request to GPM var response = await client.GetAsync($"https://gtapolicemods.com/dev/downloads/latest?id={GpmDownloadsId}"); // Makes sure we got a valid response back response.EnsureSuccessStatusCode(); // Checks that the version we're running IS NOT the newest version if (!CurrentVersion.Equals(await response.Content.ReadAsStringAsync())) { Debug.WriteLine("A new version of Who's Joe is available on GPM!"); } } catch (HttpRequestException) { // Our request failed, print a short message Debug.WriteLine("Couldn't check for Who's Joe updates!"); } }
Our CheckForUpdates method does two things: it reaches out to GPM (ensuring the request went through), and prints out information to the console based on what we get back.
You might notice the GpmDownloadsId being inserted into the URL we're calling. This is how GPM knows what upload to give us information on. Check out the docs for more info.
Our logic for determining if our release is current or not is very simple. We simply check if the contents of our CurrentVersion field is equal to the response we get back from GPM. If it's not, we print a message stating that a different version of "Who's Joe" is available on GPM.
Lastly, we wrapped the entire method in a "try... catch" block. This allows us to detect when something is wrong with the response and handle it. This could happen if the end user's server is not connected to the internet, or GPM is not responding to our request. Probably the former, though. In our code, we print a notice to the user that we couldn't check for updates. You may prefer to fail silently and not alert the user.
After the code has been compiled and ran, the update check appears in the console. Success.
This guide serves as an example. Specific implementations vary.
Reach out to us if you're having difficulties connecting your work to GPM. We're happy to help.
-
1