bleeter/shared/config.lua

160 lines
5.5 KiB
Lua
Raw Normal View History

Soziales Netz im Spiel: Feed, Werbung, Markt, Kalender und Gewerbe Jeder Spieler waehlt sich ein Handle mit @, Unternehmen und Behoerden bekommen eigene Profile, fuer die sie Mitarbeiter freigeben. Verwaltet wird ueber dieselbe Anmeldung wie das Webhosting: wer am IC-Computer als Anbieter angemeldet ist, richtet Unternehmensprofile ein. Damit gibt es genau eine Stelle, an der Verwaltungsrechte haengen - ein zweites Rechtesystem daneben waere eine zweite Stelle, an der man jemanden zu entziehen vergisst. Bewusst getrennt: wer fuer ein Unternehmen schreiben darf, kann sich nicht selbst zum Verwalter machen. Behoben gegenueber dem Ausgangsstand: - Die Resource startete nicht. Eine harte Abhaengigkeit zeigte auf eine Resource, die es nicht gibt - das verhindert den Start vollstaendig. - Das Schema war gegenueber dem Code stehengeblieben: eine Tabelle fehlte ganz, sechs Spalten fehlten. Jede Registrierung eines Handles scheiterte deshalb mit einem SQL-Fehler. Zwei Migrationen ziehen das nach. - Die Identitaet kommt jetzt von ESX statt von einem Charaktersystem, das hier nicht laeuft. Ohne das findet das Mailsystem die Postfaecher nicht. - Das Fenster hatte keinen Schliessknopf, nur ESC. Im Computerfenster ist diese Taste aber schon vergeben. - Bilder laden mit referrerpolicy="no-referrer": Bilderdienste sperren Hotlinks anhand der Herkunft, und die eines NUI kennen sie nicht. - Der Schluessel fuer den Bilder-Upload steht nicht mehr im Code, sondern in der server.cfg (set bleeter_imgbb_key). Er gehoert nicht in ein oeffentlich einsehbares Repository. Neu: Unternehmensprofile und Mitarbeiterfreigabe, ueber Netzwerkereignisse und Konsolenbefehle. Dazu eine Oberflaeche im IC-Computer, die dieselbe Gestaltung benutzt - die Stildatei wird dafuer mechanisch gekapselt, statt sie nachzubauen. Enthaelt README.md mit Einrichtung, Rechten und den Fallstricken.
2026-08-09 12:00:48 +00:00
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