QB / ESX
Agency-LifeinvaderV3
Modern advertisement system for FiveM with custom Liquid Glass UI, tiered pricing based on character count, and ad queue management. Supports ad categories with filtering, priority/boost ads, anonymous posting, and database persistence via oxmysql. Includes admin panel for approving/deleting ads and works with ESX, QBCore, and Standalone.

01 Configuration
Complete config.lua for Agency-LifeinvaderV3. All options documented via inline comments.
--[[ ═══════════════════════════════════════════
AGENCY LIFEINVADER V3 - CONFIGURATION
by Agency Scripts
═══════════════════════════════════════════ ]]
Config = {}
-- Framework auto-detection (ESX, QBCore, or standalone)
Config.Framework = 'auto'
-- Enable Database Integration (MySQL/MariaDB via oxmysql)
-- If false: Ads are not saved through restarts, recent feed is empty, settings are reset, and
-- admin panel cannot fetch or edit previous ads. Good for temporary servers.
Config.UseDatabase = true
-- Debug mode (set to true for detailed console/chat messages)
Config.Debug = false
-- Localization
-- Available: en, de, fr, es, it, pt, pl, nl, tr, ru, cs, sv, da, no, ro
Config.Locale = 'en'
Config.Localization = {
fallbackLocale = 'en', -- Missing translation keys fall back to English automatically
useLocaleNotifications = true
}
-- Use Agency Notify system
Config.UseAgencyNotify = true
-- ═══ UI BRANDING ══════════════════════════════
-- Customize the name and logo shown in all UI panels.
-- Change "BrandName" to match your server name (e.g. "WEAZEL NEWS", "LS ADVERTISER", etc.)
-- "BrandSubtitle" is the small text shown below the brand name in the main menu header.
-- "LogoFile" is the path to your logo image.
-- Option 1: Just the filename if it's in the web/ folder (e.g. "logo.png")
-- Option 2: Full nui:// path (e.g. "nui://Agency-LifeinvaderV3/web/logo.png")
-- Option 3: "" (empty string) to use the default SVG icon instead of an image
-- The logo should be a white/light-colored PNG with transparent background for best results.
-- IMPORTANT: Make sure your logo file is listed in the "files" block of fxmanifest.lua!
Config.UI = {
BrandName = 'LIFEINVADER', -- Main title shown in the menu header (uppercase recommended)
BrandSubtitle = 'Ad Agency v3', -- Subtitle shown below the brand name
LogoFile = 'nui://Agency-LifeinvaderV3/web/logo.png', -- Logo path ("" = use default icon)
}
-- ═══ COMMANDS ═══════════════════════════════
-- All commands are configurable. Prefix "al" = Agency Lifeinvader
Config.Commands = {
main = 'alad', -- Open ad creation menu
recent = 'alfeed', -- Open recent ads feed
test = 'altest', -- Show a test notification
admin = 'aladmin' -- Open admin panel
}
-- ═══ KEY BINDINGS ═══════════════════════════
-- Key to open the main menu (F6 = 167)
Config.OpenKey = 167
-- Key to open recent ads menu (F5 = 166)
Config.RecentKey = 166
-- ═══ ADVERTISEMENT SETTINGS ═════════════════
Config.Price = 5000 -- Base price per ad
Config.MaxReps = 5 -- Maximum repetitions
Config.MinInterval = 30 -- Minimum interval in seconds
Config.MaxInterval = 300 -- Maximum interval in seconds
Config.MaxLength = 300 -- Maximum message length
Config.DisplayDuration = 8000 -- Default how long notifications show (ms)
Config.MaxDisplayDuration = 60 -- Max display duration players can choose (seconds)
Config.CostPerSecond = 500 -- Additional cost per second of display duration
Config.TickerInterval = 15 -- How often the server checks for ads (seconds)
Config.InitialDelay = 0 -- Default delay before first send
Config.NotificationColor = '#3b82f6' -- Global accent color for all notifications
-- ═══ AD CATEGORIES ═════════════════════════
Config.Categories = {
{ id = 'jobs', label = 'Jobs', emoji = '💼' },
{ id = 'vehicles', label = 'Vehicles', emoji = '🚗' },
{ id = 'realestate', label = 'Real Estate', emoji = '🏠' },
{ id = 'services', label = 'Services', emoji = '🔧' },
{ id = 'events', label = 'Events', emoji = '🎉' },
{ id = 'other', label = 'Other', emoji = '📌' }
}
-- Category-specific behavior (language-neutral, reused by UI + server logic)
Config.CategoryRules = {
jobs = {
priceMultiplier = 0.9, -- Price multiplier (0.9 = 10% cheaper)
priorityBonus = 2, -- Queue priority boost
requireApproval = false, -- Require admin approval for this category
maxRepetitions = 4, -- Max repetitions for this category
minInterval = 30 -- Min interval in seconds for this category
},
vehicles = {
priceMultiplier = 1.15,
priorityBonus = 1,
requireApproval = false,
maxRepetitions = 5,
minInterval = 45
},
realestate = {
priceMultiplier = 1.25,
priorityBonus = 1,
requireApproval = true,
maxRepetitions = 4,
minInterval = 60
},
services = {
priceMultiplier = 1.0,
priorityBonus = 2,
requireApproval = false,
maxRepetitions = 5,
minInterval = 30
},
events = {
priceMultiplier = 1.1,
priorityBonus = 3,
requireApproval = false,
maxRepetitions = 5,
minInterval = 30
},
other = {
priceMultiplier = 1.0,
priorityBonus = 0,
requireApproval = false,
maxRepetitions = 3,
minInterval = 45
}
}
-- ═══ AGENCY EMPLOYEE PANEL ═════════════════
-- Configure a job/company whose employees can access the Agency panel.
-- Employees can manage ads and earn commission from each ad placed through them.
Config.Agency = {
enabled = true,
command = 'alagency', -- Command to open the agency panel
-- Job/company requirements (framework-dependent)
job = 'lifeinvader', -- Job name (ESX/QBCore job)
minGrade = 0, -- Minimum grade/rank required
-- Commission settings
commissionPercent = 10, -- Percentage of ad revenue paid to the employee
commissionType = 'cash', -- 'cash' or 'bank'
-- Agency account (shared company money pot)
useCompanyAccount = true, -- If true, ad revenue goes to a shared account
companyAccountName = 'lifeinvader_agency', -- Account identifier for company funds
}
-- ═══ ANONYMOUS ADS ═════════════════════════
Config.AllowAnonymous = true -- Allow players to post anonymously
-- ═══ BOOST SYSTEM ══════════════════════════
Config.BoostMultiplier = 2 -- Price multiplier for boosted ads (2x)
Config.BoostEnabled = true -- Enable the boost feature
-- ═══ ADMIN SETTINGS ═════════════════════════
Config.Admin = {
-- Who can use the admin panel?
-- 'ace' = uses ace permissions (group.admin)
-- 'identifier' = uses a list of identifiers
-- 'framework' = uses framework admin detection
permissionType = 'ace',
-- If permissionType = 'identifier', list allowed identifiers
allowedIdentifiers = {
-- 'license:xxxx',
-- 'steam:xxxx',
},
-- Require admin approval before ads go live?
requireApproval = false,
-- Maximum ads shown in admin panel
maxAdsInPanel = 50
}
-- ═══ V3 FEATURE FLAGS ════════════════════════
Config.Features = {
agencyAI = true, -- Enable heuristic AI moderation
playerLimits = true, -- Enable cooldown/limit system
adminLogs = true, -- Show activity logs in admin panel
adminBulkActions = true, -- Allow bulk approve/reject/delete in admin panel
adminActivityFeed = true, -- Show recent activity feed in admin panel
adminLogDetails = true, -- Show detailed log entries
adminSearch = true, -- Enable search bar in admin panel
adminStats = true, -- Show statistics in admin panel
scheduleOverview = true, -- Show schedule overview in history tab
queueInsights = true, -- Show queue insights in history tab
pendingEditing = true, -- Allow editing pending (under review) ads
categoryRules = true, -- Enable category rules system
scheduling = true, -- Enable ad scheduling
draftTitleEditing = true, -- Allow naming drafts
drafts = true -- Enable draft system
}
-- ═══ PLAYER LIMITS / FLOW CONTROL ════════════
Config.PlayerLimits = {
cooldownSeconds = 45, -- Time between ad submissions
maxPendingAds = 3, -- Max waiting-for-review ads per player
maxActiveAds = 4, -- Max currently running approved ads per player
adminBypass = true -- Allow admins to bypass these limits
}
-- ═══ SCHEDULING ══════════════════════════════
Config.Scheduling = {
enabled = true,
maxMinutesAhead = 1440 -- How far ahead players can schedule (1440 = 24 hours)
}
-- ═══ AGENCY AI (HEURISTIC, NO EXTERNAL AI) ═══
-- Built-in heuristic system that flags suspicious ads for manual review.
-- This does NOT use any external AI API — it runs locally on the server.
Config.AgencyAI = {
enabled = true,
autoNormalizeWhitespace = true, -- Auto-clean excessive whitespace
forceApprovalOnFlag = true, -- Force admin approval when AI flags an ad
scoreThreshold = 4, -- Penalty score threshold to trigger a flag
duplicateWindowMinutes = 30, -- Time window to check for duplicate ads
duplicateThreshold = 1, -- How many duplicates before flagging
externalLinkPatterns = { -- Patterns that count as external links
'http://',
'https://',
'www.',
'discord.gg',
'bit.ly'
},
suspiciousTerms = { -- Terms that trigger a penalty
'@everyone',
'free money',
'hack',
'exploit',
'cheap cash',
'real money'
},
categoryPriority = { -- Queue priority bonus per category
events = 3,
jobs = 2,
services = 2,
vehicles = 1,
realestate = 1,
other = 0
},
boostedBonus = 8, -- Extra priority score for boosted ads
penalties = { -- Penalty scores per violation type
duplicate_message = 3,
aggressive_frequency = 2,
excessive_caps = 1,
excessive_symbols = 1,
external_link = 2,
contact_heavy = 1,
suspicious_term = 2,
long_copy = 1
}
}
-- ═══ AI TEXT GENERATION ═════════════════════
-- Generate professional ad copy using AI. Players can click "Generate" in the ad form.
-- API key can also be set via server.cfg: set lifeinvader_ai_key "your-key"
Config.AIGeneration = {
enabled = true,
-- Provider: 'groq', 'openai', 'perplexity', 'claude'
provider = 'groq',
-- API keys per provider (leave empty to use server convar "lifeinvader_ai_key")
apiKeys = {
groq = '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',
openai = '',
perplexity = '',
claude = ''
},
-- Recommended models per provider
models = {
groq = 'llama-3.1-8b-instant',
openai = 'gpt-4o-mini',
perplexity = 'llama-3.1-sonar-small-128k-online',
claude = 'claude-haiku-4-5-20251001'
},
-- API endpoints per provider
endpoints = {
groq = 'https://api.groq.com/openai/v1/chat/completions',
openai = 'https://api.openai.com/v1/chat/completions',
perplexity = 'https://api.perplexity.ai/chat/completions',
claude = 'https://api.anthropic.com/v1/messages'
},
-- Generation settings
maxTokens = 200,
temperature = 0.8,
-- System prompt for generating ad text
systemPrompt = 'You are an advertising copywriter for Lifeinvader (a social media platform in GTA/FiveM). Write short, catchy advertisement texts in the language the user writes in. Keep it under 250 characters. Be creative, professional and persuasive. Include a catchy title line followed by the ad body. Do NOT use hashtags or emojis. Respond ONLY with the ad text, nothing else.'
}
-- ═══ PLAYER SETTINGS (DEFAULTS) ═════════════
-- Default values for player-configurable settings.
-- Players can change these in their settings menu (gear icon).
Config.PlayerSettingsDefaults = {
notificationPosition = {x = 0, y = 50}, -- Default position (left side, vertically centered)
notificationEnabled = true, -- Can players disable ad notifications?
notificationScale = 1.0, -- Default UI scale (0.8 to 1.4)
uiTransparency = 0.55, -- Menu background opacity (0.1 to 1.0)
soundEnabled = true -- Play sounds on new ads?
}
-- ═══ SOUNDS ═════════════════════════════════
-- Native GTA sounds (soundName, soundSet)
Config.Sounds = {
openMenu = { name = "SELECT", set = "HUD_FRONTEND_DEFAULT_SOUNDSET" },
closeMenu = { name = "CANCEL", set = "HUD_FRONTEND_DEFAULT_SOUNDSET" },
submitAd = { name = "PURCHASE", set = "HUD_LIQUOR_STORE_SOUNDSET" },
newAd = { name = "TEXT_ARRIVE_TONE", set = "HUD_AWARDS" }
}
-- ═══ NOTIFICATION SETTINGS ══════════════════
Config.AdNotification = {
enabled = true,
position = {x = 0, y = 50}, -- Default position (left side, vertically centered)
duration = 6000, -- Display duration in milliseconds
maxWidth = 380, -- Max notification width in pixels
showAuthor = true -- Show who posted the ad
}
-- ═══ MONEY SETTINGS ═════════════════════════
Config.Money = {
type = "cash", -- "cash" or "bank"
removeOnSubmit = true, -- Set to false if you handle money elsewhere
agencyPay = true -- Allow payment via Agency-Pay (requires agency-phone)
}
-- ═══ NOTIFICATION MESSAGES ══════════════════
-- These are the server-side notification texts sent to players.
Config.Notification = {
useAgencyNotify = true,
successMessage = "Advertisement submitted successfully!",
errorMessage = "Not enough money to submit advertisement!",
pendingMessage = "Your ad has been submitted and is awaiting admin approval.",
adminPendingMessage = "A new advertisement is waiting for admin review.",
approvedMessage = "Your ad has been approved and will be broadcast soon!",
rejectedMessage = "Your ad has been rejected by an admin.",
aiPendingMessage = "Agency AI flagged your ad for review before it can go live.",
cooldownMessage = "Please wait %s seconds before submitting another advertisement.",
pendingLimitMessage = "You already have %s advertisements waiting for review.",
activeLimitMessage = "You already have %s active advertisements running."
}