Bleeter gehoert in den IC-Computer: dort sitzt man an einem Geraet, statt mitten auf der Strasse ein Fenster aufzuklappen. Ein Chatbefehl umgeht das und macht die Oberflaeche ueberall verfuegbar. Der Export OpenBleeter bleibt, damit andere Resources sie oeffnen koennen - etwa ein Telefon. Config.Command faellt weg, ohne Befehl hat es keine Bedeutung.
159 lines
5.5 KiB
Lua
159 lines
5.5 KiB
Lua
Config = {}
|
|
|
|
Config.Debug = false
|
|
Config.Locale = 'de'
|
|
|
|
Config.Ui = {
|
|
alwaysLandscape = true,
|
|
defaultPage = 'feed'
|
|
}
|
|
|
|
Config.Handles = {
|
|
forceLowercase = true,
|
|
pattern = '^[a-z0-9%._%-]+$',
|
|
minLength = 2,
|
|
maxLength = 32
|
|
}
|
|
|
|
Config.Media = {
|
|
provider = 'imgbb',
|
|
-- Kein Schluessel im Code: die Datei liegt in der Versionsverwaltung.
|
|
-- Der echte Wert gehoert in die server.cfg:
|
|
-- set bleeter_imgbb_key "dein-schluessel"
|
|
-- Ein Wert hier wirkt als Rueckfallebene, etwa fuer eine Testumgebung.
|
|
imgbbApiKey = '',
|
|
maxBytes = 2 * 1024 * 1024,
|
|
allowedExtensions = { 'jpg', 'jpeg', 'png' },
|
|
allowExternalUrls = true,
|
|
requireHttps = true,
|
|
storage = 'external'
|
|
}
|
|
|
|
Config.Moderation = {
|
|
restoreDays = 5
|
|
}
|
|
|
|
Config.ProfileTypes = {
|
|
private = 'Privat',
|
|
small_business = 'Kleingewerbe',
|
|
company = 'Unternehmen',
|
|
authority = 'Behörde',
|
|
lifeinvader = 'Lifeinvader'
|
|
}
|
|
|
|
Config.Navigation = {
|
|
{ key = 'feed', label = 'Feed', icon = 'home' },
|
|
{ key = 'ads', label = 'Werbefeed', icon = 'megaphone' },
|
|
{ key = 'followers', label = 'Follower', icon = 'users' },
|
|
{ key = 'market', label = 'Marktplatz', icon = 'basket' },
|
|
{ key = 'calendar', label = 'Kalender', icon = 'calendar' },
|
|
{ key = 'business', label = 'Gewerbe', icon = 'briefcase' },
|
|
{ key = 'profile', label = 'Profil', icon = 'user' },
|
|
{ key = 'legal', label = 'Rechtliches',icon = 'book' }
|
|
}
|
|
|
|
-- ── Identität ─────────────────────────────────────────────────────────────────
|
|
-- Alle Funktionen sind server-only und werden nur serverseitig aufgerufen.
|
|
|
|
-- ESX, wenn vorhanden. Wird bei Bedarf geholt, nicht beim Laden: beim Start
|
|
-- ist es je nach Reihenfolge noch nicht bereit.
|
|
local _esx
|
|
local function esx()
|
|
if _esx then return _esx end
|
|
if GetResourceState('es_extended') ~= 'started' then return nil end
|
|
local ok, obj = pcall(function() return exports['es_extended']:getSharedObject() end)
|
|
if ok then _esx = obj end
|
|
return _esx
|
|
end
|
|
|
|
local function xPlayer(source)
|
|
local api = esx()
|
|
return api and api.GetPlayerFromId(source) or nil
|
|
end
|
|
|
|
function Config.GetIdentifier(source)
|
|
-- ESX fuehrt seine eigene Identifierliste. Sie muss hier dieselbe sein,
|
|
-- sonst findet ic-mail die Postfaecher dieser Person nicht.
|
|
local player = xPlayer(source)
|
|
if player and player.identifier then return player.identifier end
|
|
|
|
return GetPlayerIdentifierByType(source, 'license') or GetPlayerIdentifiers(source)[1]
|
|
end
|
|
|
|
-- Charakter-Id. Auf einem ESX-Server ist das der ESX-Identifier; core-characters
|
|
-- gibt es hier nicht, wird aber weiter unterstuetzt.
|
|
function Config.GetCharacterId(source)
|
|
if GetResourceState('core-characters') == 'started' then
|
|
local ok, cid = pcall(function()
|
|
return exports['core-characters']:GetCitizenId(source)
|
|
end)
|
|
if ok and cid and cid ~= '' then return cid end
|
|
end
|
|
return Config.GetIdentifier(source)
|
|
end
|
|
|
|
-- Anzeigename: ESX-Charaktername, sonst core-characters, sonst Spielername.
|
|
function Config.GetCharacterName(source)
|
|
local player = xPlayer(source)
|
|
if player then
|
|
if player.getName then
|
|
local ok, name = pcall(player.getName)
|
|
if ok and name and name ~= '' then return name end
|
|
end
|
|
if player.name and player.name ~= '' then return player.name end
|
|
end
|
|
|
|
if GetResourceState('core-characters') == 'started' then
|
|
local ok, name = pcall(function()
|
|
return exports['core-characters']:GetCharacterName(source)
|
|
end)
|
|
if ok and name and name ~= '' then return name end
|
|
end
|
|
|
|
return GetPlayerName(source) or ('Spieler %s'):format(source)
|
|
end
|
|
|
|
-- Primäre IC-Mailadresse aus ic-mail (single source of truth).
|
|
-- Gibt '' zurück wenn noch keine Adresse konfiguriert wurde.
|
|
function Config.GetMailAddress(source)
|
|
local charId = Config.GetCharacterId(source)
|
|
if not charId or charId == '' then return '' end
|
|
if GetResourceState('ic-mail') == 'started' then
|
|
local ok, addr = pcall(function()
|
|
return exports['ic-mail']:GetPrimaryAddress(charId)
|
|
end)
|
|
if ok and addr and addr ~= '' then return addr end
|
|
end
|
|
-- Fallback: direkt aus DB (falls ic-mail nicht erreichbar)
|
|
local ok2, row = pcall(function()
|
|
return MySQL.single.await(
|
|
'SELECT address FROM ic_mail_accounts WHERE owner_identifier = ? AND account_type = ? AND is_active = 1 LIMIT 1',
|
|
{ charId, 'personal' }
|
|
)
|
|
end)
|
|
if ok2 and row and row.address and row.address ~= '' then
|
|
return row.address
|
|
end
|
|
return ''
|
|
end
|
|
|
|
-- Telefonnummer aus zc_ifruit, Fallback: zc_ifruit Export
|
|
function Config.GetPhoneNumber(source)
|
|
local charId = Config.GetCharacterId(source)
|
|
if charId and charId ~= '' then
|
|
local ok, row = pcall(function()
|
|
return MySQL.single.await(
|
|
'SELECT active_number FROM zc_ifruit_accounts WHERE char_id = ? LIMIT 1',
|
|
{ charId }
|
|
)
|
|
end)
|
|
if ok and row and row.active_number then
|
|
return tostring(row.active_number)
|
|
end
|
|
end
|
|
if GetResourceState('zc_ifruit') == 'started' then
|
|
local ok2, num = pcall(function() return exports['zc_ifruit']:GetPhoneNumber(source) end)
|
|
if ok2 and num then return tostring(num) end
|
|
end
|
|
return nil
|
|
end
|