Cross-Language Pingback Implementation

Implement pingback functionality seamlessly across Node.js, PHP, Python, and JavaScript. Below are code snippets demonstrating how to send pingbacks to your server using each language. Replace fillUserId with your user ID and fillYourServerId with your server ID:

Navigate to your dashboard, where you can edit your server details and incorporate a callback URL to reward your users for voting. This feature enables you to incentivize and acknowledge user participation effectively.

PHP (using cURL)

<?php

$userId = 'fillUserId';
$serverId = 'fillYourServerId';
$timestamp = date('c');

$data = array(
    'userId' => $userId,
    'serverId' => $serverId,
    'timestamp' => $timestamp
);

$ch = curl_init('https://gtopservers.com/pingback');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));

$response = curl_exec($ch);

if ($response === false) {
    echo 'Error sending pingback: ' . curl_error($ch);
} else {
    echo 'Response from server: ' . $response;
}

curl_close($ch);

?>

PHP Callback Script

<?php

    include("config.php");
    
    // Get the raw POST data
    $postData = file_get_contents("php://input");
    // Decode the JSON data
    $requestData = json_decode($postData, true);
    
    // Access the userId from the decoded JSON data
    $user = $requestData['userId'];
    
    // Prepare the SQL query using a prepared statement
    $query = "UPDATE users SET credits = credits + 100 WHERE login = ?";
    $stmt = mysqli_prepare($mysqli, $query);
    
    // Bind the parameter
    mysqli_stmt_bind_param($stmt, "s", $user);
    
    // Execute the statement
    mysqli_stmt_execute($stmt);
    
    // Check if the update was successful
    if (mysqli_stmt_affected_rows($stmt) > 0) {
        echo json_encode(['message' => 'Credits updated successfully']);
    } else {
        echo json_encode(['message' => 'Failed to update credits']);
    }
    
    // Close the statement
    mysqli_stmt_close($stmt);
    ?>

Python (using Requests)


import requests
from datetime import datetime

def send_pingback():
    url = 'https://gtopservers.com/pingback'
    user_id = 'fillUserId'
    server_id = 'fillYourServerId'
    timestamp = datetime.now().isoformat()

    data = {
        'userId': user_id,
        'serverId': server_id,
        'timestamp': timestamp
    }

    try:
        response = requests.post(url, json=data)
        print('Response from server:', response.json())
    except requests.exceptions.RequestException as e:
        print('Error sending pingback:', e)

# Call the function to send a pingback
send_pingback()

Python (Flask) Callback Endpoint

from flask import Flask, request, jsonify
    app = Flask(__name__)
    
    # Example in-memory "database"
    users = [
        { 'userId': 'user123', 'credits': 100 }
    ]
    
    @app.route('/callback', methods=['POST'])
    def callback():
        requestData = request.get_json()
    
        # Access the userId from the JSON data
        userId = requestData['userId']
    
        # Update user credits
        for user in users:
            if user['userId'] == userId:
                user['credits'] += 100
                return jsonify({'message': 'Credits updated successfully'})
    
        return jsonify({'message': 'User not found or credits not updated'}), 404
    
    if __name__ == '__main__':
        app.run(debug=True)
    

JavaScript (using Fetch API)

<script type="text/javascript">
const sendPingback = async () => {
    try {
        const userId = 'fillUserId';
        const serverId = 'fillYourServerId';
        const timestamp = new Date().toISOString();

        const response = await fetch('https://gtopservers.com/pingback', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ userId, serverId, timestamp })
        });

        const responseData = await response.json();
        console.log('Response from server:', responseData);
    } catch (error) {
        console.error('Error sending pingback:', error);
    }
};

// Call the function to send a pingback
sendPingback();
</script>

Node.js (using Axios)


const axios = require('axios');

const sendPingback = async () => {
try {
    const userId = 'fillUserId';
    const serverId = 'fillYourServerId';
    const timestamp = new Date().toISOString();

    const response = await axios.post('https://gtopservers.com/pingback', {
        userId,
        serverId,
        timestamp
    });

    console.log('Response from server:', response.data);
} catch (error) {
    console.error('Error sending pingback:', error);
}
};

sendPingback();

Node.js (Express) Callback Endpoint

const express = require('express');
    const bodyParser = require('body-parser');
    const app = express();
    const port = 3000;
    
    // Example in-memory "database"
    let users = [
        { userId: 'user123', credits: 0 }
    ];
    
    // Middleware to parse JSON bodies
    app.use(bodyParser.json());
    
    // POST endpoint for handling pingback
    app.post('/callback', (req, res) => {
        const { userId } = req.body;
    
        // Update user credits in "database"
        for (let i = 0; i < users.length; i++) {
            if (users[i].userId === userId) {
                users[i].credits += 100;
                return res.json({ message: 'Credits updated successfully' });
            }
        }
    
        return res.status(404).json({ message: 'User not found or credits not updated' });
    });
    
    app.listen(port, () => {
        console.log(`Server running at http://localhost:${port}`);
    });
    

Rust Voting Script

To enhance your Rust server's engagement, integrate the gtopservers.cs file into your Umod plugins. This enables your players to vote for the server and earn rewards, enhancing their in-game experience through features like a coin system and an interactive shop.

Commands:

  • /vote - Allows players to vote for the server.
  • /coins - Enables players to check their current coin balance.
  • /shop - Opens the shop interface for players to purchase items.

Implementing this script not only encourages player participation but also enriches gameplay by offering tangible rewards and interactive features.

using Oxide.Core;
    using Oxide.Core.Plugins;
    using System.Collections.Generic;
    using Newtonsoft.Json;
    using UnityEngine;
    using Oxide.Game.Rust.Cui;
    
    namespace Oxide.Plugins
    {
        [Info("GTopServersVote", "Gtopservers", "1.0.0")]
        [Description("Allows players to vote for rewards on gtopservers.com")]
        class GTopServersVote : RustPlugin
        {
            private Dictionary playerBalances = new Dictionary();
            private const string voteApiUrl = "https://gtopservers.com/api/vote/";
    
            // Define a list of items with their names, shortnames, amounts, costs, and image URLs
            private List itemList = new List
            {
                new ItemInfo { Name = "Scrap", Shortname = "scrap", Amount = 100, Cost = 50, ImageUrl = "https://rustlabs.com/img/items180/scrap.png" },
                new ItemInfo { Name = "Rifle Ammo", Shortname = "ammo.rifle", Amount = 100, Cost = 100, ImageUrl = "https://rustlabs.com/img/items180/ammo.rifle.png" },
                new ItemInfo { Name = "Wood", Shortname = "wood", Amount = 100, Cost = 75, ImageUrl = "https://rustlabs.com/img/items180/wood.png" }
            };
    
            private class ItemInfo
            {
                public string Name { get; set; }
                public string Shortname { get; set; }
                public int Amount { get; set; }
                public int Cost { get; set; }
                public string ImageUrl { get; set; }
            }
    
            [ChatCommand("vote")]
            void VoteCommand(BasePlayer player, string command, string[] args)
            {
                string userId = player.UserIDString;
                string serverId = "your-server-id"; // Replace this with your server ID
                int reward = 100; // Replace this with amount you will reward your players
    
                Dictionary requestData = new Dictionary
                {
                    { "userId", player.UserIDString }
                };
    
                string jsonPayload = JsonConvert.SerializeObject(requestData);
    
                webrequest.EnqueuePost(voteApiUrl + serverId, jsonPayload, (code, response) =>
                {
                    if (code != 200 || response == null)
                    {
                        player.ChatMessage("Error voting, please try again later.");
                        return;
                    }
    
                    var jsonResponse = JsonConvert.DeserializeObject>(response);
                    if (jsonResponse["status"].ToString() == "success")
                    {
                        AddCoins(player.UserIDString, reward);
                        player.ChatMessage("Thank you for voting! You have been rewarded.");
                    }
                    else
                    {
                        player.ChatMessage(jsonResponse["message"].ToString());
                    }
                }, this);
            }
    
            void AddCoins(string userId, int amount)
            {
                if (!playerBalances.ContainsKey(userId))
                {
                    playerBalances[userId] = 0;
                }
    
                playerBalances[userId] += amount;
            }
    
            [ChatCommand("coins")]
            void CoinsCommand(BasePlayer player, string command, string[] args)
            {
                int balance = GetCoins(player.UserIDString);
                player.ChatMessage($"You have {balance} GTopServers coins.");
            }
    
            int GetCoins(string userId)
            {
                if (playerBalances.ContainsKey(userId))
                {
                    return playerBalances[userId];
                }
                return 0;
            }
    
            [ChatCommand("shop")]
            void ShopCommand(BasePlayer player, string command, string[] args)
            {
                ShowShopUI(player);
            }
    
            [ConsoleCommand("shop.buy")]
            void BuyCommand(ConsoleSystem.Arg arg)
            {
                BasePlayer player = arg.Player();
                if (player == null) return;
    
                string[] args = arg.Args;
                if (args.Length < 1)
                {
                    player.ChatMessage("Invalid command syntax.");
                    return;
                }
    
                string itemName = args[0].ToLower();
                ItemInfo itemInfo = itemList.Find(x => x.Shortname.ToLower() == itemName);
    
                if (itemInfo == null)
                {
                    player.ChatMessage("Item not found in shop.");
                    return;
                }
    
                int itemCost = itemInfo.Cost;
                int playerBalance = GetCoins(player.UserIDString);
                if (playerBalance >= itemCost)
                {
                    // Subtract the item cost from the player's balance
                    AddCoins(player.UserIDString, -itemCost);
                    player.ChatMessage($"You have purchased {itemInfo.Name}.");
    
                    // Add item to player's inventory
                    ItemManager.CreateByName(itemInfo.Shortname, itemInfo.Amount)?.MoveToContainer(player.inventory.containerMain);
                }
                else
                {
                    player.ChatMessage("You do not have enough coins to purchase this item.");
                }
    
                DestroyUI(player); // Close the shop UI after purchase
            }
    
            void ShowShopUI(BasePlayer player)
            {
                DestroyUI(player);
    
                var container = new CuiElementContainer();
    
                // Get player's coin balance
                int balance = GetCoins(player.UserIDString);
    
                var panel = container.Add(new CuiPanel
                {
                    Image = { Color = "0.1 0.1 0.1 0.8" },
                    RectTransform = { AnchorMin = "0.2 0.2", AnchorMax = "0.8 0.8" },
                    CursorEnabled = true
                }, "Overlay", "ShopUI");
    
                container.Add(new CuiLabel
                {
                    Text = { Text = $"Gtopservers Shop (Coins: {balance})", FontSize = 24, Align = TextAnchor.UpperCenter },
                    RectTransform = { AnchorMin = "0 0.9", AnchorMax = "1 1" }
                }, panel);
    
                // Calculate vertical position for each row
                float startY = 0.7f;
                float rowHeight = 0.2f;
    
                // Calculate horizontal position for each item within a row
                float startX = 0.1f;
                float itemWidth = 0.16f; // Adjust this value to change the spacing between items
    
                int itemsPerRow = 6;
                int itemCount = 0;
    
                foreach (var item in itemList)
                {
                    // Calculate the position of the current item within the row
                    float xPos = startX + (itemWidth * (itemCount % itemsPerRow));
                    float yPos = startY - (rowHeight * Mathf.Floor(itemCount / itemsPerRow));
    
                    // Add item image
                   container.Add(new CuiElement
                    {
                        Parent = panel,
                        Components =
                        {
                            new CuiRawImageComponent { Url = item.ImageUrl },
                            new CuiRectTransformComponent { AnchorMin = $"{xPos} {yPos + rowHeight / 4}", AnchorMax = $"{xPos + itemWidth} {yPos + rowHeight / 2}" }
                        }
                    });
    
                    // Add item name
                    container.Add(new CuiLabel
                    {
                        Text = { Text = item.Name, FontSize = 14, Align = TextAnchor.MiddleCenter },
                        RectTransform = { AnchorMin = $"{xPos} {yPos - rowHeight / 8}", AnchorMax = $"{xPos + itemWidth} {yPos + rowHeight / 4}" }
                    }, panel);
    
                    // Add buy button
                    container.Add(new CuiButton
                    {
                        Button = { Color = "0.7 0.2 0.2 1", Command = $"shop.buy {item.Shortname.ToLower()}" },
                        RectTransform = { AnchorMin = $"{xPos} {yPos - rowHeight}", AnchorMax = $"{xPos + itemWidth} {yPos - rowHeight / 2}" },
                        Text = { Text = $"Buy ({item.Cost} coins)", FontSize = 14, Align = TextAnchor.MiddleCenter }
                    }, panel);
    
                    itemCount++;
                }
    
                container.Add(new CuiButton
                {
                    Button = { Color = "0.8 0.2 0.2 1", Command = "shop.close" },
                    RectTransform = { AnchorMin = "0.1 0.1", AnchorMax = "0.9 0.2" },
                    Text = { Text = "Close", FontSize = 18, Align = TextAnchor.MiddleCenter }
                }, panel);
    
                CuiHelper.AddUi(player, container);
            }
    
            [ConsoleCommand("shop.close")]
            void CloseShopUICommand(ConsoleSystem.Arg arg)
            {
                BasePlayer player = arg.Player();
                if (player == null) return;
                DestroyUI(player);
            }
    
            void DestroyUI(BasePlayer player)
            {
                CuiHelper.DestroyUi(player, "ShopUI");
            }
        }
    }