World of Warcraft
Overview
Reward your WoW private server players for voting on topgservers. This guide covers two approaches: a C++ core script for TrinityCore/AzerothCore, and a Lua Eluna script for easier deployment. Both poll the vote-check API and can grant gold, items, or custom rewards.
Prerequisites
- A WoW private server running TrinityCore or AzerothCore
- Eluna Lua engine (recommended) or C++ core compilation setup
- topgservers API key — generate one in My Servers → API
- Webhook secret (optional, for real-time rewards via a sidecar)
- cURL development libraries (libcurl) if using C++ approach
Installation
1 Choose your approach
Eluna (Lua) is recommended for most servers — no recompilation needed. The C++ approach is for servers that need maximum performance or don't have Eluna.
lua_scripts/
└── topg_vote.lua 2 Create the Eluna script
Place the Lua script in your server's `lua_scripts/` directory. It will be loaded automatically on server start.
-- topgservers Vote Checker for Eluna (TrinityCore / AzerothCore)
local API_KEY = "tgs_your_api_key_here"
local CHECK_INTERVAL = 60000 -- milliseconds
local REWARD_ITEM_ID = 29434 -- Badge of Justice (example)
local REWARD_COUNT = 5
local rewarded = {}
local function CheckVote(event, player)
local name = player:GetName()
if rewarded[name] then return end
-- Eluna HTTP requires the HttpRequest module or
-- an external vote-check script (see below)
end 3 Set up the external vote checker
Since Eluna has limited HTTP support, use a companion script that writes vote results to a file or database that the Lua script reads.
#!/bin/bash
# Cron: * * * * * /path/to/vote_checker.sh
API_KEY="tgs_your_api_key_here"
DB_NAME="world"
DB_USER="trinity"
# Get online character names from the database
PLAYERS=$(mysql -u$DB_USER -p -D characters -se "SELECT name FROM characters WHERE online = 1")
for PLAYER in $PLAYERS; do
RESPONSE=$(curl -s -H "Authorization: Bearer $API_KEY" "https://topgservers.net/api/v1/vote-check?username=$PLAYER")
VOTED=$(echo "$RESPONSE" | grep -o '"voted":true')
if [ -n "$VOTED" ]; then
# Insert into a custom votes table for the Lua script to read
mysql -u$DB_USER -p -D $DB_NAME -e "INSERT IGNORE INTO topg_votes (name, date) VALUES ('$PLAYER', CURDATE())"
fi
done Configuration
-- Configuration
local CONFIG = {
apiKey = "tgs_your_api_key_here",
webhookSecret = "whsec_your_secret_here",
checkInterval = 60000, -- ms between checks
-- Rewards
rewardItemId = 29434, -- Badge of Justice
rewardCount = 5,
rewardGold = 100, -- gold (not copper)
rewardMessage = "Thanks for voting on topgservers!",
} Vote Check
Call the /api/v1/vote-check endpoint to determine if a player has voted today.
-- Read from the topg_votes table populated by the cron script
local function ProcessVotes(event, player)
local name = player:GetName()
local query = CharDBQuery(string.format(
"SELECT 1 FROM topg_votes WHERE name = '%s' AND date = CURDATE() AND rewarded = 0",
name
))
if query then
-- Mark as rewarded
CharDBExecute(string.format(
"UPDATE topg_votes SET rewarded = 1 WHERE name = '%s' AND date = CURDATE()",
name
))
GrantReward(player)
end
end
-- Check on player login and periodically
RegisterPlayerEvent(3, ProcessVotes) -- PLAYER_EVENT_ON_LOGIN Webhook Receiver
Verify the X-TopG-Signature header using HMAC-SHA256 to ensure webhook payloads are authentic.
"""
Lightweight webhook receiver for WoW servers.
Run alongside your game server. Inserts into the topg_votes table
so the Eluna script can pick up rewards.
"""
import hmac, hashlib, json, mysql.connector
from http.server import HTTPServer, BaseHTTPRequestHandler
WEBHOOK_SECRET = "whsec_your_secret_here"
DB_CONFIG = {
"host": "127.0.0.1",
"user": "trinity",
"password": "password",
"database": "characters"
}
class WebhookHandler(BaseHTTPRequestHandler):
def do_POST(self):
length = int(self.headers.get('Content-Length', 0))
body = self.rfile.read(length).decode()
sig = self.headers.get('X-TopG-Signature', '')
if not verify_signature(body, sig):
self.send_response(401)
self.end_headers()
return
data = json.loads(body)
username = data.get('username', '')
if username:
db = mysql.connector.connect(**DB_CONFIG)
cursor = db.cursor()
cursor.execute(
"INSERT IGNORE INTO topg_votes (name, date) VALUES (%s, CURDATE())",
(username,)
)
db.commit()
db.close()
self.send_response(200)
self.end_headers()
def verify_signature(body, sig_header):
parts = dict(p.split('=', 1) for p in sig_header.split(',') if '=' in p)
timestamp = parts.get('t', '')
received = parts.get('v1', '')
expected = hmac.new(
WEBHOOK_SECRET.encode(),
f"{timestamp}.{body}".encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, received)
if __name__ == '__main__':
server = HTTPServer(('0.0.0.0', 8090), WebhookHandler)
print("Webhook receiver listening on :8090")
server.serve_forever() Reward Examples
function GrantReward(player)
-- Give item (e.g., Badge of Justice x5)
player:AddItem(CONFIG.rewardItemId, CONFIG.rewardCount)
-- Give gold (in copper: 1 gold = 10000 copper)
player:ModifyMoney(CONFIG.rewardGold * 10000)
-- Send mail with item
SendMail(
"Vote Reward", -- subject
"Thanks for voting on topgservers!", -- body
player:GetGUIDLow(), -- receiver
0, -- sender (0 = system)
61, -- stationery
0, -- delay
0, -- money
0, -- cod
CONFIG.rewardItemId, -- item entry
CONFIG.rewardCount -- item count
)
player:SendBroadcastMessage(CONFIG.rewardMessage)
end Notes & Tips
The hybrid approach (cron/sidecar + DB + Eluna) is battle-tested on large private servers. Create the `topg_votes` table with: `CREATE TABLE topg_votes (name VARCHAR(50), date DATE, rewarded TINYINT DEFAULT 0, PRIMARY KEY(name, date));` For AzerothCore specifically, Eluna is bundled by default.