Automatizzare il diritto all'oblio utilizzando i webhook

*Questo contenuto è tradotto usando AI (Beta) e potrebbe contenere errori. Per visualizzare questa pagina in inglese, clicca qui.

Le normative globali sulla protezione dei dati e sulla privacy concedono agli individui il diritto di controllare i propri dati, incluso il diritto di richiederne la cancellazione (spesso definito come "diritto all'oblio" o "diritto di cancellazione"). Se memorizzi dati personali o Informazioni Personamente Identificabili (PII), come gli ID utente, sei responsabile della conformità ai relativi framework di privacy, eliminando permanentemente queste informazioni al ricevimento di una richiesta da parte dell'utente. Maggiori informazioni possono essere trovate in RTBF e creatori.

Considera alternative

Per i dati personali nei data store, l'opzione di automazione più semplice è configurare i modelli di cancellazione RTBF. Quando Roblox elabora una richiesta RTBF, elimina automaticamente le voci corrispondenti nei data store standard o ordinati senza richiedere di ospitare codice personalizzato. Per configurare i modelli e rivedere i modelli supportati, vedere Diritto all'oblio (RTBF) nei data store.

Il flusso di lavoro del webhook in questa pagina è utile quando:

  • Memorizzi dati personali al di fuori dei data store.
  • Il tuo schema di data store o caso d'uso non è supportato dai modelli di cancellazione RTBF.
  • Hai bisogno di logica di elaborazione o cancellazione personalizzata.

Flusso di lavoro del webhook per creatori

Questo tutorial dimostra come configurare un webhook e creare un bot Discord in esecuzione localmente che utilizza l'Open Cloud API per i data store per automatizzare la gestione delle richieste di diritto all'oblio. Il flusso di lavoro per questo processo è il seguente:

  1. Il supporto Roblox riceve una richiesta di diritto all'oblio da un utente.
  2. Il webhook di Roblox viene attivato, contenente l'ID utente e un elenco di ID di Start Place per i giochi a cui hanno partecipato nel payload.
  3. Il tuo bot ascolta queste notifiche webhook, verifica la loro autenticità e utilizza l'Open Cloud API per i data store per eliminare i dati PII memorizzati nei data store.
  4. Il bot risponde al messaggio del webhook in Discord con lo stato della cancellazione.

Configura un webhook con integrazione di terze parti

Prima di creare un bot, configura un server con integrazione webhook sull'applicazione di messaggistica di terze parti. Quindi utilizza il server per configurare un webhook nel Creator Dashboard.

Configura un server

I seguenti passaggi mostrano come configurare il server utilizzando Discord.

  1. Crea un nuovo server Discord. Se non sei familiare con il processo, consulta Supporto Discord.

  2. Il server crea automaticamente un canale #general come canale predefinito. Fai clic sull'icona Modifica canale del canale #general.

  3. Sotto Permessi, imposta il canale come privato.

  4. Crea un'integrazione webhook con il nuovo server, chiamandola RTBF Hook. Se non sei familiare con il processo, consulta Supporto Discord.

  5. Copia l'URL del webhook e conservalo in un luogo sicuro. Consenti solo ai membri fidati del team di accedervi, poiché la divulgazione dell'URL può consentire a soggetti malintenzionati di inviare messaggi falsi e potenzialmente eliminare i tuoi dati utente.

Configura un webhook su Roblox

Dopo aver ottenuto l'URL del server di terze parti, utilizzalo per configurare un webhook nel Creator Dashboard. Assicurati di eseguire le seguenti impostazioni:

  • Aggiungi l'URL del server Discord come Webhook URL.
  • Includi un Segreto personalizzato. Sebbene un segreto sia facoltativo per completare la configurazione, dovresti includerne uno per prevenire che soggetti malintenzionati impersonino Roblox e cancellino i tuoi dati. Per ulteriori informazioni sull'uso di un segreto, consulta Verifica della sicurezza del webhook.
  • Seleziona Richiesta di diritto all'oblio sotto Trigger.

Puoi testare il webhook utilizzando il pulsante Test Response per vedere se ricevi una notifica nel canale #general del tuo server da Roblox. Se non ricevi la notifica, riprova o controlla le impostazioni del tuo server per risolvere l'errore.

Configura un bot

Dopo aver aggiunto il webhook, utilizzalo per configurare il bot seguendo i seguenti passaggi. Per ulteriori informazioni, consulta la documentazione di Discord.

  1. Crea una nuova applicazione e chiamala RTBF Bot.
  2. Il sistema ti reindirizza alle impostazioni di Informazioni generali del bot. Copia e salva il suo ID applicazione in un luogo sicuro.
  3. Sotto il menu delle impostazioni, seleziona OAuth2.
  4. Naviga alle impostazioni di OAuth2
    1. Abilita l'ambito bot, verrà visualizzato un elenco di ulteriori permessi per il bot.
    2. Aggiungi il permesso Amministratore. Salva le modifiche.
    3. Salva l'URL generato.
  5. Copia l'URL generato. Lascia aperta la pagina delle impostazioni dell'applicazione.
  6. Naviga all'URL generato. Seleziona il server di destinazione. Fai clic sul pulsante Continua e poi sul pulsante Autorizza.
  7. Torna alla pagina delle impostazioni dell'applicazione e naviga alle impostazioni del Bot.
  8. Nella sezione Intenzioni di gateway privilegiate, abilita Intento contenuto messaggi.
  9. Nelle impostazioni del Bot > sezione Build-A-Bot, salva il token del bot in un luogo sicuro per i passaggi successivi. Se non vedi il token, fai clic sul pulsante Reimposta token per generare uno nuovo.

Crea una chiave API Open Cloud

Per consentire al tuo bot di terze parti di accedere ai tuoi data store per memorizzare i dati PII degli utenti, crea una chiave API Open Cloud che possa accedere ai tuoi giochi e aggiungi il permesso Elimina voce dei data store per la cancellazione dei dati. Se utilizzi data store ordinati per memorizzare PII, devi anche aggiungere il permesso Scrivi dei data store ordinati. Dopo aver completato, copia e salva la chiave API in un luogo sicuro per utilizzarla nei passaggi successivi.

Ottieni identificatori di giochi e luoghi

Affinché il bot possa localizzare i dati PII richiesti dagli utenti per la cancellazione, ottieni i seguenti identificatori di tutti i giochi per i quali intendi utilizzare il bot:

  • L'ID Universale, l'identificatore unico del tuo gioco.
  • L'ID di Start Place, l'identificatore unico del luogo di partenza di un gioco.

Per ottenere questi identificatori:

  1. Naviga al Creator Dashboard.

  2. Passa sopra la miniatura di un gioco, fai clic sul pulsante e seleziona Copia ID Universale e Copia ID di Start Place, rispettivamente.

Aggiungi script

Dopo aver completato la configurazione del webhook, del bot e della chiave API per i data store, aggiungili agli script che implementano la logica di automazione del bot. Il seguente esempio utilizza Python 3.

  1. Installa le librerie Python utilizzando i seguenti comandi:

    Installa librerie
    pip3 install discord
    pip3 install requests
    pip3 install urllib3==1.26.6
  2. Copia e salva i seguenti script corrispondenti a diverse parti della logica del bot nella stessa directory:

    bot_config.py
    BOT_TOKEN = ""
    OPEN_CLOUD_API_KEY = ""
    ROBLOX_WEBHOOK_SECRET = ""
    # Dizionario dell'ID di Start Place a
    # (ID universale, elenco di (nome dei data store, ambito e chiave di voce)) per
    # Data Store Standard
    # I dati utente memorizzati sotto queste voci verranno eliminati
    STANDARD_DATA_STORE_ENTRIES = {
    # ID di Start Place
    111111111: (
    # ID Universale
    222222222,
    [
    ("StandardDataStore1", "Scope1", "Key1_{user_id}"),
    ("StandardDataStore1", "Scope1", "Key2_{user_id}"),
    ("StandardDataStore2", "Scope1", "Key3_{user_id}")
    ]
    ),
    33333333: (
    444444444,
    [
    ("StandardDataStore3", "Scope1", "Key1_{user_id}")
    ]
    )
    }
    # Dizionario dell'ID di Start Place a
    # (ID universale, elenco di (nome dei data store, ambito e chiave di voce)) per
    # Data Store Ordinati
    # I dati utente memorizzati sotto queste voci verranno eliminati
    ORDERED_DATA_STORE_ENTRIES = {
    111111111: (
    222222222,
    [
    ("OrderedDataStore1", "Scope2", "Key4_{user_id}")
    ]
    )
    }
    data_stores_api.py
    import requests
    import bot_config
    from collections import defaultdict
    """
    Chiama l'Open Cloud API dei Data Store per eliminare tutte le voci per un user_id configurato in
    STANDARD_DATA_STORE_ENTRIES. Restituisce un elenco di cancellazioni riuscite e fallite.
    """
    def delete_standard_data_stores(user_id, start_place_ids):
    successes = defaultdict(list)
    failures = defaultdict(list)
    for owned_start_place_id in bot_config.STANDARD_DATA_STORE_ENTRIES:
    if owned_start_place_id not in start_place_ids:
    continue
    universe_id, universe_entries = bot_config.STANDARD_DATA_STORE_ENTRIES[owned_start_place_id]
    for (data_store_name, scope, entry_key) in universe_entries:
    entry_key = entry_key.replace("{user_id}", user_id)
    response = requests.delete(
    f"https://apis.roblox.com/datastores/v1/universes/{universe_id}/standard-datastores/datastore/entries/entry",
    headers={"x-api-key": bot_config.OPEN_CLOUD_API_KEY},
    params={
    "datastoreName": data_store_name,
    "scope": scope,
    "entryKey": entry_key
    }
    )
    if response.status_code in [200, 204]:
    successes[owned_start_place_id].append((data_store_name, scope, entry_key))
    else:
    failures[owned_start_place_id].append((data_store_name, scope, entry_key))
    return successes, failures
    """
    Chiama l'Open Cloud API dei Data Store Ordinati per eliminare tutte le voci per un user_id configurato in
    ORDERED_DATA_STORE_ENTRIES. Restituisce un elenco di cancellazioni riuscite e fallite.
    """
    def delete_ordered_data_stores(user_id, start_place_ids):
    successes = defaultdict(list)
    failures = defaultdict(list)
    for owned_start_place_id in bot_config.ORDERED_DATA_STORE_ENTRIES:
    if owned_start_place_id not in start_place_ids:
    continue
    universe_id, universe_entries = bot_config.ORDERED_DATA_STORE_ENTRIES[owned_start_place_id]
    for (data_store_name, scope, entry_key) in universe_entries:
    entry_key = entry_key.replace("{user_id}", user_id)
    response = requests.delete(
    f"https://apis.roblox.com/ordered-data-stores/v1/universes/{universe_id}/orderedDatastores/{data_store_name}/scopes/{scope}/entries/{entry_key}",
    headers={"x-api-key": bot_config.OPEN_CLOUD_API_KEY}
    )
    if response.status_code in [200, 204, 404]:
    successes[owned_start_place_id].append((data_store_name, scope, entry_key))
    else:
    failures[owned_start_place_id].append((data_store_name, scope, entry_key))
    return successes, failures
    message_parser.py
    import time
    import hmac
    import hashlib
    import re
    import base64
    import bot_config
    """
    Analizza il messaggio ricevuto per la firma e il timestamp di Roblox, il footer è impostato solo se hai
    configurato il segreto del webhook
    """
    def parse_footer(message):
    if not message.embeds[0].footer or \
    not message.embeds[0].footer.text:
    return "", 0
    footer_match = re.match(
    r"Roblox-Signature: (.*), Timestamp: (.*)",
    message.embeds[0].footer.text
    )
    if not footer_match:
    return "", 0
    else:
    signature = footer_match.group(1)
    timestamp = int(footer_match.group(2))
    return signature, timestamp
    """
    Verifica la firma di Roblox con il segreto configurato per controllare la validità
    """
    def validate_signature(message, signature, timestamp):
    if not message or not signature or not timestamp:
    return False
    # Previene attacchi di ripetizione all'interno di una finestra di 300 secondi
    request_timestamp_ms = timestamp * 1000
    window_time_ms = 300 * 1000
    oldest_timestamp_allowed = round(time.time() * 1000) - window_time_ms
    if request_timestamp_ms < oldest_timestamp_allowed:
    return False
    # Valida la firma
    timestamp_message = "{}.{}".format(timestamp, message.embeds[0].description)
    digest = hmac.new(
    bot_config.ROBLOX_WEBHOOK_SECRET.encode(),
    msg=timestamp_message.encode(),
    digestmod=hashlib.sha256
    ).digest()
    validated_signature = base64.b64encode(digest).decode()
    if signature != validated_signature:
    return False
    # Firma valida
    return True
    """
    Analizza un messaggio webhook ricevuto su Discord. Estrae l'ID utente, previene attacchi di ripetizione
    basati sul timestamp ricevuto e verifica la firma di Roblox con il segreto configurato per controllare la validità.
    """
    def parse_message(message):
    # Analizza il messaggio ricevuto per l'ID utente e l'ID del gioco
    if len(message.embeds) != 1 or \
    not message.embeds[0].description:
    return "", []
    description_match = re.match(
    r"Hai ricevuto una nuova notifica per il diritto all'oblio per l'ID utente: (.*) nel " +
    r"gioco(i) con ID: (.*)",
    message.embeds[0].description
    )
    if not description_match:
    return "", []
    user_id = description_match.group(1)
    start_place_ids = set(int(item.strip()) for item in description_match.group(2).split(","))
    signature, timestamp = parse_footer(message)
    if validate_signature(message, signature, timestamp):
    return user_id, start_place_ids
    else:
    return "", []
    discord_bot.py
    import discord
    import bot_config
    import data_stores_api
    import message_parser
    def run():
    intents = discord.Intents.default()
    intents.message_content = True
    client = discord.Client(intents=intents)
    @client.event
    async def on_ready():
    print(f"{client.user} sta ascoltando i messaggi sul diritto all'oblio")
    """
    Gestore per i messaggi webhook da Roblox
    """
    @client.event
    async def on_message(message):
    # Analizza e valida il messaggio
    user_id, start_place_ids = message_parser.parse_message(message)
    if not user_id or not start_place_ids:
    return
    # Elimina i dati utente dai data store standard
    [successes, failures] = data_stores_api.delete_standard_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Dati dei data store standard eliminati per " +
    f"ID utente: {user_id}, dati: {dict(successes)}")
    if failures:
    await message.reply(f"Impossibile eliminare i dati dei data store standard per " +
    f"ID utente: {user_id}, dati: {dict(failures)}")
    # Elimina i dati utente dai data store ordinati
    [successes, failures] = data_stores_api.delete_ordered_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Dati dei data store ordinati eliminati per " +
    f"ID utente: {user_id}, dati: {dict(successes)}")
    if failures:
    await message.reply(f"Impossibile eliminare i dati dei data store ordinati per " +
    f"ID utente: {user_id}, dati: {dict(failures)}")
    client.run(bot_config.BOT_TOKEN)
    if __name__ == "__main__":
    run()
  3. Nel file bot_config.py per la configurazione principale del bot:

    1. Imposta BOT_TOKEN sul token generato dal tuo bot.
    2. Imposta OPEN_CLOUD_API_KEY come la chiave API che hai creato.
    3. Imposta ROBLOX_WEBHOOK_SECRET come il segreto che hai impostato quando hai configurato il webhook nel Creator Dashboard.
    4. Nei dizionari STANDARD_DATA_STORE_ENTRIES e ORDERED_DATA_STORE_ENTRIES per localizzare il data store di ciascun record da eliminare:
      1. Aggiungi i tuoi ID di Start Place copiati come chiavi.
      2. Aggiungi gli ID Universali come primo elemento della tupla valore.
      3. Sostituisci il secondo elemento della tupla con il nome, l'ambito, il nome della chiave di voce e l'ID utente associato dei tuoi data store. Se utilizzi uno schema di dati diverso, modifica per adattarlo al tuo schema di dati.
  4. Esegui il seguente comando per avviare il bot:

    Esegui il bot Discord
    python3 discord_bot.py
  5. Il bot inizia quindi ad ascoltare e verificare i webhook di Roblox per le richieste di diritto all'oblio e chiama l'endpoint Open Cloud per eliminare il corrispondente data store.

Test

Puoi creare ed eseguire un messaggio di test per verificare che il tuo programma personalizzato possa gestire correttamente le richieste di diritto all'oblio e cancellare i dati PII:

  1. Invia una richiesta HTTP POST al tuo server webhook Discord con il seguente corpo della richiesta:

    Esempio di richiesta
    curl -X POST {serverUrl}
    -H 'Content-Type: application/json'
    -d '{
    "embeds":[{
    "title":"RichiestaDirittoAllOblio",
    "description":"Hai ricevuto una nuova notifica per il diritto all'oblio per l'ID utente: {userIds} nel gioco(i) con ID: {gameIds}",
    "footer":{
    "icon_url":"https://create.roblox.com/dashboard/assets/webhooks/roblox_logo_metal.png",
    "text":"Roblox-Signature: {robloxSignature}, Timestamp: {timestamp}"
    }
    }]
    }'
  2. Se hai un segreto webhook:

    1. Genera una Roblox-Signature applicando la codifica HMAC-SHA256 alla tua chiave segreta del webhook.
    2. Imposta l'ora corrente utilizzando il timestamp UTC in secondi come Timestamp.
  3. Metti insieme la description nel seguente formato:

    Formato del campo descrizione
    {Timestamp}. Hai ricevuto una nuova notifica per il diritto all'oblio per l'ID utente: {userId} nel gioco(i) con ID: {gameIds}`.

    Ad esempio:

    Esempio di campo descrizione
    1683927229. Hai ricevuto una nuova notifica per il diritto all'oblio per l'ID utente: 2425654247 nel gioco(i) con ID: 10539205763, 13260950955

Il tuo programma dovrebbe essere in grado di identificare che il tuo messaggio proviene dalla fonte ufficiale di Roblox poiché hai codificato il messaggio con il tuo segreto. Dovrebbe quindi eliminare i dati PII associati alla tua richiesta.

Esempio di corpo
{
"embeds": [
{
"title": "RichiestaDirittoAllOblio",
"description": "Hai ricevuto una nuova notifica per il diritto all'oblio per l'ID utente: 2425654247 nel gioco(i) con ID: 10539205763, 13260950955",
"footer": {
"icon_url": "https://create.roblox.com/dashboard/assets/webhooks/roblox_logo_metal.png",
"text": "Roblox-Signature: UIe6GJ78MHCmU/zUKBYP3LV0lAqwWRFR6UEfPt1xBFw=, Timestamp: 1683927229"
}
}
]
}
© 2026 Roblox Corporation. Roblox, il logo Roblox e Powering Imagination sono tra i nostri marchi registrati e non registrati negli Stati Uniti. e altri paesi.