Automatisasi permintaan hak untuk dihapus

*Konten ini diterjemahkan menggunakan AI (Beta) dan mungkin mengandung kesalahan. Untuk melihat halaman ini dalam bahasa Inggris, klik di sini.

Regulasi perlindungan data dan privasi global memberikan individu hak untuk mengontrol data mereka, termasuk hak untuk meminta penghapusannya (sering disebut sebagai "hak untuk dihapus" atau "hak untuk menghapus"). Jika Anda menyimpan data pribadi atau Informasi Identifikasi Pribadi (PII), seperti ID Pengguna, Anda bertanggung jawab untuk mematuhi kerangka kerja privasi yang berlaku dengan menghapus informasi ini secara permanen setelah menerima permintaan dari pengguna. Informasi lebih lanjut dapat ditemukan di RTBF dan kreator.

Alih-alih menangani permintaan secara manual, Anda dapat mengatur webhook dan menggunakan bot dalam aplikasi pesan pihak ketiga untuk mengotomatiskan proses tersebut. Karena penyimpanan data adalah cara yang paling umum untuk menyimpan data PII, tutorial ini memberikan contoh cara membuat bot di Discord yang menggunakan Open Cloud API untuk penyimpanan data untuk menghapus data PII sebagai solusi otomatisasi.

Alur kerja

Setelah menyelesaikan tutorial ini, Anda seharusnya dapat membuat program kustom yang berjalan secara lokal yang mengotomatiskan penanganan permintaan hak untuk dihapus dari pengguna. Alur kerja untuk proses ini adalah sebagai berikut:

  1. Dukungan Roblox menerima permintaan hak untuk dihapus dari seorang pengguna.
  2. Webhook Roblox diaktifkan, berisi ID Pengguna dan daftar ID Tempat Awal untuk permainan yang telah mereka ikuti dalam payload.
  3. Bot Anda mendengarkan notifikasi webhook ini, memverifikasi keasliannya, dan memanfaatkan Open Cloud API untuk penyimpanan data untuk menghapus data PII yang tersimpan di penyimpanan data.
  4. Bot merespons pesan webhook di Discord dengan status penghapusan.

Konfigurasi webhook dengan integrasi pihak ketiga

Sebelum membuat bot, atur server dengan integrasi webhook di aplikasi pesan pihak ketiga. Kemudian gunakan server untuk mengonfigurasi webhook di Dasbor Pembuat.

Atur server

Langkah-langkah berikut menunjukkan cara mengatur server menggunakan Discord.

  1. Buat server Discord baru. Jika Anda tidak familiar dengan proses tersebut, lihat Dukungan Discord.

  2. Server secara otomatis membuat saluran #general sebagai saluran default Anda. Klik ikon Edit Channel dari saluran #general.

  3. Di bawah Permissions, atur saluran menjadi pribadi.

  4. Buat integrasi webhook dengan server baru, namai RTBF Hook. Jika Anda tidak familiar dengan proses tersebut, lihat Dukungan Discord.

  5. Salin URL webhook dan simpan di tempat yang aman. Hanya izinkan anggota tim tepercaya untuk mengaksesnya, karena membocorkan URL dapat memungkinkan aktor jahat untuk mengirim pesan palsu dan berpotensi menghapus data pengguna Anda.

Konfigurasi webhook di Roblox

Setelah memperoleh URL server pihak ketiga, gunakan untuk mengonfigurasi webhook di Dasbor Pembuat. pastikan Anda melakukan pengaturan berikut:

  • Tambahkan URL server Discord sebagai Webhook URL.
  • Sertakan Secret kustom. Meskipun secret adalah opsional untuk menyelesaikan konfigurasi, Anda harus menyertakannya untuk mencegah aktor jahat berpura-pura menjadi Roblox dan menghapus data Anda. Untuk informasi lebih lanjut tentang penggunaan secret, lihat Verifikasi keamanan webhook.
  • Pilih Permintaan Hak untuk Dihapus di bawah Triggers.

Anda dapat menguji webhook menggunakan tombol Tes Respons untuk melihat apakah Anda menerima notifikasi di saluran #general server Anda dari Roblox. Jika Anda tidak menerima notifikasi, coba lagi atau periksa pengaturan server Anda untuk memecahkan kesalahan.

Mengonfigurasi bot

Setelah Anda menambahkan webhook, gunakan untuk mengonfigurasi bot dengan langkah-langkah berikut. Untuk informasi lebih lanjut, lihat dokumentasi Discord.

  1. Navigasi ke Halaman Aplikasi.
  2. Buat aplikasi baru dan namai RTBF Bot.
  3. Sistem mengalihkan Anda ke pengaturan Informasi Umum bot. Salin dan simpan ID aplikasi di tempat yang aman.
  4. Di bawah menu pengaturan, pilih OAuth2.
  5. Navigasikan ke pengaturan OAuth2
    1. Aktifkan ruang lingkup bot, daftar izin Bot tambahan akan ditampilkan.
    2. Tambahkan izin Administrator. Simpan perubahan Anda.
    3. Simpan URL yang dihasilkan.
  6. Salin URL yang dihasilkan. Tinggalkan halaman pengaturan aplikasi tidak ditutup.
  7. Navigasikan ke URL yang dihasilkan. Pilih server target. Klik tombol Lanjutkan dan kemudian tombol Otorisasi.
  8. Kembali ke halaman pengaturan aplikasi dan navigasikan ke pengaturan Bot.
  9. Di bawah bagian Privileged Gateway Intents, aktifkan Message Content Intent.
  10. Di pengaturan Bot > bagian Build-A-Bot, simpan token bot di tempat yang aman untuk langkah selanjutnya. Jika Anda tidak melihat token, klik tombol Reset Token untuk menghasilkan yang baru.

Buat kunci API Open Cloud

Untuk memungkinkan bot pihak ketiga Anda mengakses penyimpanan data Anda untuk menyimpan PII pengguna, buat kunci API Open Cloud yang dapat mengakses permainan Anda dan menambahkan izin Hapus Entri dari penyimpanan data untuk penghapusan data. Jika Anda menggunakan penyimpanan data yang terurut untuk menyimpan PII, Anda juga perlu menambahkan izin Tulis penyimpanan data yang terurut. Setelah selesai, salin dan simpan kunci API di lokasi yang aman untuk digunakan di langkah-langkah selanjutnya.

Peroleh pengidentifikasi permainan dan tempat

Agar bot dapat menemukan data PII yang diminta oleh pengguna untuk dihapus, peroleh pengidentifikasi berikut dari semua permainan yang Anda berniat menggunakan bot:

  • Universe ID, pengidentifikasi unik permainan Anda.
  • Start Place ID, pengidentifikasi unik tempat awal dari sebuah permainan.

Untuk memperoleh pengidentifikasi ini:

  1. Navigasikan ke Dasbor Pembuat.

  2. Arahkan kursor ke thumbnail permainan, klik tombol , dan pilih Salin Universe ID dan Salin Start Place ID, masing-masing.

Tambahkan skrip

Setelah Anda selesai mengatur webhook, bot, dan kunci API untuk penyimpanan data, tambahkan ke skrip yang menerapkan logika otomatisasi bot. Contoh berikut menggunakan Python 3.

  1. Instal pustaka Python menggunakan perintah berikut:

    Instal Pustaka
    pip3 install discord
    pip3 install requests
    pip3 install urllib3==1.26.6
  2. Salin dan simpan skrip berikut yang sesuai dengan bagian yang berbeda dari logika bot di direktori yang sama:

    bot_config.py
    BOT_TOKEN = ""
    OPEN_CLOUD_API_KEY = ""
    ROBLOX_WEBHOOK_SECRET = ""
    # Kamus ID Start Place ke
    # (universe ID, daftar (nama penyimpanan data, scope, dan entry key)) untuk
    # Penyimpanan Data Standar
    # Data pengguna yang disimpan di bawah entri ini akan dihapus
    STANDARD_DATA_STORE_ENTRIES = {
    # Start Place ID
    111111111: (
    # Universe ID
    222222222,
    [
    ("StandardDataStore1", "Scope1", "Key1_{user_id}"),
    ("StandardDataStore1", "Scope1", "Key2_{user_id}"),
    ("StandardDataStore2", "Scope1", "Key3_{user_id}")
    ]
    ),
    33333333: (
    444444444,
    [
    ("StandardDataStore3", "Scope1", "Key1_{user_id}")
    ]
    )
    }
    # Kamus ID Start Place ke
    # (universe ID, daftar (nama penyimpanan data, scope, dan entry key)) untuk
    # Penyimpanan Data Terurut
    # Data pengguna yang disimpan di bawah entri ini akan dihapus
    ORDERED_DATA_STORE_ENTRIES = {
    111111111: (
    222222222,
    [
    ("OrderedDataStore1", "Scope2", "Key4_{user_id}")
    ]
    )
    }
    data_stores_api.py
    import requests
    import bot_config
    from collections import defaultdict
    """
    Memanggil API Open Cloud Penyimpanan Data untuk menghapus semua entri untuk user_id yang dikonfigurasi di
    STANDARD_DATA_STORE_ENTRIES. Mengembalikan daftar penghapusan yang berhasil dan kegagalan untuk menghapus.
    """
    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
    """
    Memanggil API Open Cloud Penyimpanan Data Terurut untuk menghapus semua entri untuk user_id yang dikonfigurasi di
    ORDERED_DATA_STORE_ENTRIES. Mengembalikan daftar penghapusan yang berhasil dan kegagalan untuk menghapus.
    """
    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
    """
    Menganalisis pesan yang diterima untuk tanda tangan Roblox dan timestamp, footer hanya disetel jika Anda
    mengonfigurasi secret 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
    """
    Memverifikasi tanda tangan Roblox dengan secret yang dikonfigurasi untuk memeriksa keabsahan
    """
    def validate_signature(message, signature, timestamp):
    if not message or not signature or not timestamp:
    return False
    # Mencegah serangan replay dalam jendela 300 detik
    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
    # Memvalidasi tanda tangan
    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
    # Tanda tangan yang valid
    return True
    """
    Menganalisis pesan webhook yang diterima di Discord. Mengambil ID pengguna, mencegah serangan replay
    berdasarkan timestamp yang diterima, dan memverifikasi tanda tangan Roblox dengan secret yang dikonfigurasi untuk memeriksa keabsahan.
    """
    def parse_message(message):
    # Menganalisis pesan yang diterima untuk ID pengguna dan ID permainan
    if len(message.embeds) != 1 or \
    not message.embeds[0].description:
    return "", []
    description_match = re.match(
    r"You have received a new notification for Right to Erasure for the User Id: (.*) in " +
    r"the game\(s\) with Ids: (.*)",
    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} sedang mendengarkan pesan Hak untuk Dihapus")
    """
    Penangan untuk pesan webhook dari Roblox
    """
    @client.event
    async def on_message(message):
    # Menganalisis dan memvalidasi pesan
    user_id, start_place_ids = message_parser.parse_message(message)
    if not user_id or not start_place_ids:
    return
    # Menghapus data pengguna dari penyimpanan data standar
    [successes, failures] = data_stores_api.delete_standard_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Data penyimpanan data standar dihapus untuk " +
    f"ID pengguna: {user_id}, data: {dict(successes)}")
    if failures:
    await message.reply(f"Gagal menghapus data penyimpanan data standar untuk " +
    f"ID pengguna: {user_id}, data: {dict(failures)}")
    # Menghapus data pengguna dari penyimpanan data terurut
    [successes, failures] = data_stores_api.delete_ordered_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Data penyimpanan data terurut dihapus untuk " +
    f"ID pengguna: {user_id}, data: {dict(successes)}")
    if failures:
    await message.reply(f"Gagal menghapus data penyimpanan data terurut untuk " +
    f"ID pengguna: {user_id}, data: {dict(failures)}")
    client.run(bot_config.BOT_TOKEN)
    if __name__ == "__main__":
    run()
  3. Di file bot_config.py untuk konfigurasi utama bot:

    1. Atur BOT_TOKEN ke token yang dihasilkan oleh bot Anda.
    2. Atur OPEN_CLOUD_API_KEY sebagai kunci API yang Anda buat.
    3. Atur ROBLOX_WEBHOOK_SECRET sebagai secret yang Anda atur saat mengonfigurasi webhook di Dasbor Pembuat.
    4. Di kamus STANDARD_DATA_STORE_ENTRIES dan ORDERED_DATA_STORE_ENTRIES untuk menemukan penyimpanan data dari setiap catatan yang akan dihapus:
      1. Tambahkan ID Tempat Awal yang Anda salin sebagai kunci.
      2. Tambahkan ID Universe sebagai elemen pertama dari nilai tuple.
      3. Ganti elemen kedua dari tuple dengan nama, scope, nama entry key, dan ID Pengguna yang terkait dari penyimpanan data Anda. Jika Anda menggunakan skema data yang berbeda, modifikasi agar sesuai dengan skema data Anda sendiri.
  4. Eksekusi perintah berikut untuk menjalankan bot:

    Jalankan Bot Discord
    python3 discord_bot.py
  5. Bot kemudian mulai mendengarkan dan memverifikasi webhook Roblox untuk permintaan hak untuk dihapus dan memanggil endpoint Open Cloud untuk menghapus penyimpanan data yang sesuai.

Uji

Anda dapat membuat dan menjalankan pesan uji untuk memverifikasi bahwa program kustom Anda dapat menangani permintaan hak untuk dihapus dengan baik dan menghapus data PII:

  1. Kirim permintaan HTTP POST ke server webhook Discord Anda dengan body permintaan berikut:

    Contoh Permintaan
    curl -X POST {serverUrl}
    -H 'Content-Type: application/json'
    -d '{
    "embeds":[{
    "title":"RightToErasureRequest",
    "description":"Anda telah menerima notifikasi baru untuk Hak untuk Dihapus untuk ID Pengguna: {userIds} dalam permainan dengan ID: {gameIds}",
    "footer":{
    "icon_url":"https://create.roblox.com/dashboard/assets/webhooks/roblox_logo_metal.png",
    "text":"Roblox-Signature: {robloxSignature}, Timestamp: {timestamp}"
    }
    }]
    }'
  2. Jika Anda memiliki secret webhook:

    1. Hasilkan Roblox-Signature dengan menerapkan encoding HMAC-SHA256 pada kunci secret webhook Anda.
    2. Atur waktu saat ini menggunakan timestamp UTC dalam detik sebagai Timestamp.
  3. Rakit description dalam format berikut:

    Format Kolom Deskripsi
    {Timestamp}. Anda telah menerima notifikasi baru untuk Hak untuk Dihapus untuk ID Pengguna: {userId} dalam permainan dengan ID: {gameIds}`.

    Misalnya:

    Contoh Kolom Deskripsi
    1683927229. Anda telah menerima notifikasi baru untuk Hak untuk Dihapus untuk ID Pengguna: 2425654247 dalam permainan dengan ID: 10539205763, 13260950955

Program Anda seharusnya dapat mengidentifikasi bahwa pesan Anda berasal dari sumber resmi Roblox karena Anda telah mengenkripsi pesan dengan secret Anda. Ini harus kemudian menghapus data PII yang terkait dengan permintaan Anda.

Contoh Body
{
"embeds": [
{
"title": "RightToErasureRequest",
"description": "Anda telah menerima notifikasi baru untuk Hak untuk Dihapus untuk ID Pengguna: 2425654247 dalam permainan dengan 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, logo Roblox, dan Powering Imagination termasuk dalam merek dagang kami yang terdaftar dan tidak terdaftar di AS dan negara lainnya.