Silme talep hakkını otomatikleştirin

*Bu içerik, yapay zekâ (beta) kullanılarak çevrildi ve hatalar içerebilir. Sayfayı İngilizce görüntülemek için buraya tıkla.

Genel Veri Koruma Yönetmeliği (GDPR), veri koruma ve gizlilik hakkında Avrupa düzenlemesidir. Bireylere, kişisel verilerinin silinmesini talep etme hakkı verir, bu hak silme hakkı olarak bilinir. Kullanıcılarınızın Kişisel Olarak Tanınabilir Bilgilerini (PII) depoluyorsanız, bir kullanıcının talebi alındığında bu bilgilerin silinmesi yoluyla GDPR gerekliliklerine uymalısınız.

Talepleri elle yönetmek yerine, bir webhook ayarlayabilir ve süreci otomatikleştirmek için bir üçüncü taraf mesajlaşma uygulamasında bir bot kullanabilirsiniz. PII verilerini depolamanın en yaygın yolu veri depoları olduğu için, bu eğitimde bir Discord botu oluşturmayı ve veri depoları için Açık Bulut API'sini kullanarak PII verilerini silmeyi otomatikleştiren bir örnek verilmektedir.

İş Akışı

Bu eğitimi tamamladığınızda, kullanıcıların silme hakkı taleplerini otomatik olarak işleyen, yerel olarak çalışan özelleştirilmiş bir program oluşturabilmelisiniz. Bu süreç için iş akışı şu şekildedir:

  1. Roblox Destek, bir kullanıcıdan silme hakkı talebi alır.
  2. Roblox webhook'u, yük içinde Kullanıcı Kimliği ve katıldıkları oyunların Başlangıç Yerleri Kimlikleri listesini içeren bir bildirim gönderir.
  3. Botunuz bu webhook bildirimlerini dinler, doğruluğunu kontrol eder ve veri depolarında depolanan PII verilerini silmek için Açık Bulut API'sini kullanır.
  4. Bot, Discord'daki webhook mesajına silme durumunu yanıtlar.

Üçüncü taraf entegrasyon ile bir webhook yapılandırın

Öncelikle bir bot oluşturmadan önce, üçüncü taraf mesajlaşma uygulamasında webhook entegrasyonu ile bir sunucu oluşturun. Ardından, Creator Dashboard'da bir webhook yapılandırmak için bu sunucuyu kullanın.

Bir sunucu oluşturun

Aşağıdaki adımlar, Discord kullanarak sunucuyu nasıl kuracağınızı göstermektedir.

  1. Yeni bir Discord sunucusu oluşturun. Süreci bilmiyorsanız, lütfen Discord Destek sayfasına bakın.

  2. Sunucu otomatik olarak varsayılan kanal olarak #genel kanalını oluşturur. #genel kanalının Kanalı Düzenle simgesine tıklayın.

  3. İzinler altında, kanalı özel hale getirin.

  4. Yeni sunucu ile bir webhook entegrasyonu oluşturun, adını GDPR Hook olarak belirleyin. Süreci bilmiyorsanız, Discord Destek sayfasına başvurun.

  5. Webhook URL'sini kopyalayın ve güvenli bir yerde saklayın. URL'nin ifşa edilmesine yalnızca güvenilir ekip üyelerinin erişmesine izin verin, çünkü URL'nin sızdırılması kötü niyetli kişilerin sahte mesajlar göndermesine ve kullanıcı verilerinizi silmesine olanak tanıyabilir.

Roblox'da bir webhook yapılandırın

Üçüncü taraf sunucu URL'sini aldıktan sonra, bunu Creator Dashboard'da bir webhook yapılandırmak için kullanın, aşağıdaki ayarları kesinlikle gerçekleştirdiğinizden emin olun:

  • Discord sunucu URL'sini Webhook URL'si olarak ekleyin.
  • Özel bir Gizli Anahtar ekleyin. Gizli bir anahtar ayarları tamamlamak için isteğe bağlı olsa da, kötü niyetli kişilerden Roblox'u taklit etmelerini ve verilerinizi silmelerini önlemek için bir tane dahil etmelisiniz. Gizli anahtarın kullanımına dair daha fazla bilgi için Webhook güvenliğini doğrula sayfasına bakın.
  • Tetikler altında Silme Hakkı Talebi seçeneğini belirleyin.

Webhook'unuzu test etmek için Test Yanıtı düğmesini kullanarak Roblox'dan sunucunuzun #genel kanalında bir bildirim alıp almadığınızı kontrol edebilirsiniz. Bildirimi almazsanız, yeniden deneyin veya hata ayıklamak için sunucu ayarlarınızı kontrol edin.

Bir bot yapılandırın

Webhook'u ekledikten sonra, botu şu adımlarla yapılandırmak için kullanın. Daha fazla bilgi için lütfen Discord belgeleri sayfasına bakın.

  1. Yeni bir uygulama oluşturun ve adını GDPR Bot koyun.
  2. Sistem sizi botun Genel Bilgiler ayarlarına yönlendirecektir. Uygulama ID'sini kopyalayın ve güvenli bir yerde saklayın.
  3. Ayarlar menüsünde OAuth2'yi seçin.
  4. OAuth2 ayarlarına gidin.
    1. bot kapsamını etkinleştirin; ek Bot İzinleri listesi görüntülenecektir.
    2. Yönetici iznini ekleyin. Değişikliklerinizi kaydedin.
    3. Oluşan URL'yi kaydedin.
  5. Oluşan URL'yi kopyalayın. Uygulama ayarlar sayfasını kapatmayın.
  6. Üzerinde oluşturulan URL'ye gidin. Hedef sunucuyu seçin. Devam butonuna tıklayın ve ardından Yetkilendir butonuna tıklayın.
  7. Uygulama ayarları sayfasına geri dönün ve Bot ayarlarına gidin.
  8. Yetkili Ağ Geçidi Niyetleri bölümünde Mesaj İçeriği Niyeti'ni etkinleştirin.
  9. Bot ayarları > Bot Oluştur bölümünde bot belirtecini güvenli bir yere kaydedin; sonraki adımlar için gerekecektir. Belirteci görmüyorsanız, yeni bir tane oluşturmak için Belirteci Sıfırla butonuna tıklayın.

Açık Bulut API anahtarı oluşturun

Üçüncü taraf botunuzun kullanıcıların PII verilerini depolamak için veri depolarınıza erişebilmesi için, oyunlarınıza erişebilecek bir Açık Bulut API anahtarı oluşturun ve veri silme işlemleri için Girişi Sil iznini ekleyin. PII depolamak için sıralı veri depoları kullanıyorsanız, sıralı veri depolarının Yazma iznini de eklemeniz gerekecektir. Tamamlandıktan sonra, API anahtarını güvenli bir yerde kopyalayın ve saklayın.

Oyunların ve yerlerin kimliklerini elde etme

Botun, kullanıcılar tarafından silinmesi talep edilen PII verilerini bulabilmesi için, botu kullanmayı düşündüğünüz tüm oyunların aşağıdaki kimliklerini elde edin:

  • Evrensel Kimlik, oyununuzun benzersiz tanımlayıcısı.
  • Başlangıç Yeri Kimliği, bir oyunun başlangıç yerinin benzersiz tanımlayıcısı.

Bu kimlikleri elde etmek için:

  1. Creator Dashboard sayfasına gidin.

  2. Bir oyunun küçük resminin üzerine gelin, düğmesine tıklayın ve sırasıyla Evrensel Kimliği Kopyala ve Başlangıç Yeri Kimliği Kopyala seçeneğini belirleyin.

Betikleri ekleyin

Webhook'u, botu ve veri depoları için API anahtarını yapılandırdıktan sonra, botun otomasyon mantığını uygulayan betiklere ekleyin. Aşağıdaki örnek Python 3 kullanmaktadır.

  1. Aşağıdaki komutları kullanarak Python kütüphanelerini kurun:

    Kütüphaneleri Yükle

    pip3 install discord
    pip3 install requests
    pip3 install urllib3==1.26.6
  2. Aşağıdaki betikleri bot mantığının farklı parçalarını içerecek şekilde aynı dizine kopyalayın ve kaydedin:

    bot_config.py

    BOT_TOKEN = ""
    OPEN_CLOUD_API_KEY = ""
    ROBLOX_WEBHOOK_SECRET = ""
    # Başlangıç yeri Kimliğinden
    # (evrensel kimlik, (veri deposu adı, kapsam ve giriş anahtarı) listesi) için
    # Standart Veri Depoları
    # Bu girişlerde depolanan kullanıcı verileri silinecektir
    STANDARD_DATA_STORE_ENTRIES = {
    # Başlangıç Yeri Kimliği
    111111111: (
    # Evrensel Kimlik
    222222222,
    [
    ("StandardDataStore1", "Scope1", "Key1_{user_id}"),
    ("StandardDataStore1", "Scope1", "Key2_{user_id}"),
    ("StandardDataStore2", "Scope1", "Key3_{user_id}")
    ]
    ),
    33333333: (
    444444444,
    [
    ("StandardDataStore3", "Scope1", "Key1_{user_id}")
    ]
    )
    }
    # Başlangıç yeri Kimliğinden
    # (evrensel kimlik, (veri deposu adı, kapsam ve giriş anahtarı) listesi) için
    # Sıralı Veri Depoları
    # Bu girişlerde depolanan kullanıcı verileri silinecektir
    ORDERED_DATA_STORE_ENTRIES = {
    111111111: (
    222222222,
    [
    ("OrderedDataStore1", "Scope2", "Key4_{user_id}")
    ]
    )
    }
    data_stores_api.py

    import requests
    import bot_config
    from collections import defaultdict
    """
    Kullanıcı_id'si için tüm girişleri silmek üzere Veri Depoları Açık Bulut API'ini çağırır.
    Başarılı silmelerin ve silme hatalarının listesini döndürür.
    """
    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
    """
    Sıralı Veri Depoları Açık Bulut API'sini, kullanıcı_id'si için tüm girişleri silmek üzere çağırır.
    Başarılı silmelerin ve silme hatalarının listesini döndürür.
    """
    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
    """
    Gelen mesaj için Roblox imzasını ve zaman damgasını ayrıştırır; alt bilgi yalnızca gizli anahtar ayarladıysanız belirlenir.
    """
    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
    """
    Geçerliliği kontrol etmek için ayarlanmış gizli anahtar ile Roblox imzasını doğrular.
    """
    def validate_signature(message, signature, timestamp):
    if not message or not signature or not timestamp:
    return False
    # 300 saniyelik bir pencerede yeniden oynamayı önler
    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
    # İmza doğrular
    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
    # Geçerli imza
    return True
    """
    Discord'da alınan bir webhook mesajını ayrıştırır. Kullanıcı kimliğini çıkartır, alınan zaman damgasına dayalı yeniden oynamayı önler ve ayarlanmış gizli anahtar ile Roblox imzasını doğrular.
    """
    def parse_message(message):
    # Alınan mesaj içinde kullanıcı kimliğini ve oyun kimliğini ayrıştırır
    if len(message.embeds) != 1 or \
    not message.embeds[0].description:
    return "", []
    description_match = re.match(
    r"Silme Hakkı için Kullanıcı Id'si: (.*) ile ilgili yeni bir bildirim aldınız " +
    r"oyun\(lar\) ile Id'ler: (.*)",
    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} Silme Hakkı mesajlarını dinliyor")
    """
    Roblox'tan gelen webhook mesajları için işleyici
    """
    @client.event
    async def on_message(message):
    # Mesajı ayrıştırır ve doğrular
    user_id, start_place_ids = message_parser.parse_message(message)
    if not user_id or not start_place_ids:
    return
    # Standart veri depolarındaki kullanıcı verilerini siler
    [successes, failures] = data_stores_api.delete_standard_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Standart veri depolarındaki kullanıcı verileri silindi " +
    f"kullanıcı kimliği: {user_id}, veri: {dict(successes)}")
    if failures:
    await message.reply(f"Standart veri depolarındaki kullanıcı verileri silinemedi " +
    f"kullanıcı kimliği: {user_id}, veri: {dict(failures)}")
    # Sıralı veri depolarındaki kullanıcı verilerini siler
    [successes, failures] = data_stores_api.delete_ordered_data_stores(user_id, start_place_ids)
    if successes:
    await message.reply(f"Sıralı veri depolarındaki kullanıcı verileri silindi " +
    f"kullanıcı kimliği: {user_id}, veri: {dict(successes)}")
    if failures:
    await message.reply(f"Sıralı veri depolarındaki kullanıcı verileri silinemedi " +
    f"kullanıcı kimliği: {user_id}, veri: {dict(failures)}")
    client.run(bot_config.BOT_TOKEN)
    if __name__ == "__main__":
    run()
  3. bot_config.py dosyasında botun ana yapılandırması için:

    1. BOT_TOKEN'u botunuz tarafından üretilen belirteç ile ayarlayın.
    2. OPEN_CLOUD_API_KEY'i oluşturduğunuz API anahtarı olarak ayarlayın.
    3. ROBLOX_WEBHOOK_SECRET'i Creator Dashboard'da webhook'u yapılandırırken belirlediğiniz gizli anahtar olarak ayarlayın.
    4. STANDARD_DATA_STORE_ENTRIES ve ORDERED_DATA_STORE_ENTRIES sözlüklerinde silinecek kayıtların veri deposunu bulmak için:
      1. Kopyaladığınız Başlangıç Yeri Kimliklerini anahtar olarak ekleyin.
      2. Evrensel Kimlikleri, demetin ilk elemanı olarak ekleyin.
      3. Veri depolarınızın adını, kapsamını, giriş anahtarı adını ve ilişkili Kullanıcı Kimliğini içeren demetin ikinci elemanını değiştirin. Farklı bir veri şeması kullanıyorsanız, bunu kendi veri şemanıza uygun hale getirecek şekilde değiştirmelisiniz.
  4. Botu çalıştırmak için şu komutu uygulayın:

    Discord Botunu Çalıştır

    python3 discord_bot.py
  5. Bot, silme hakkı talepleri için Roblox webhook'larını dinlemeye ve doğrulamaya başlar ve ilgili veri deposunun silinmesi için Açık Bulut uç noktasını çağırır.

Test

Özelleştirilmiş programınızın silme hakkı taleplerini düzgün bir şekilde ele alıp almadığını doğrulamak için bir test mesajı oluşturabilir ve çalıştırabilirsiniz:

  1. Discord webhook sunucunuza aşağıdaki istek gövdesi ile bir HTTP POST isteği gönderin:

    Örnek İstek

    curl -X POST {serverUrl}
    -H 'Content-Type: application/json'
    -d '{
    "embeds":[{
    "title":"RightToErasureRequest",
    "description":"Kullanıcı Id'si: {userIds} ile oyunlardaki Silme Hakkı için yeni bir bildirim aldınız",
    "footer":{
    "icon_url":"https://create.roblox.com/dashboard/assets/webhooks/roblox_logo_metal.png",
    "text":"Roblox-Signature: {robloxSignature}, Zaman Damgası: {timestamp}"
    }
    }]
    }'
  2. Eğer bir webhook gizli anahtarınız varsa:

    1. Webhook gizli anahtarınıza HMAC-SHA256 kodlaması uygulayarak bir Roblox-Signature oluşturun.
    2. Geçerli zaman damgasını UTC zaman damgası olarak saniye cinsinden Timestamp olarak ayarlayın.
  3. description'ı aşağıdaki formatta birleştirin:

    Açıklama Alanı Formatı

    {Timestamp}. Kullanıcı Id'si: {userId} için oyunlardaki Silme Hakkı için yeni bir bildirim aldınız.

    Örneğin:

    Örnek Açıklama Alanı

    1683927229. Kullanıcı Id'si: 2425654247 için oyunlardaki Silme Hakkı için yeni bir bildirim aldınız.

Programınız, mesajınızı gizli anahtarınızla kodlandığı için resmi Roblox kaynağından geldiğini tespit edebilmelidir. Böylece, talebinizle ilişkili PII verilerini silmelidir.

Örnek Gövde

{
"embeds": [
{
"title": "RightToErasureRequest",
"description": "Kullanıcı Id'si: 2425654247 için oyunlardaki Silme Hakkı için yeni bir bildirim aldınız.",
"footer": {
"icon_url": "https://create.roblox.com/dashboard/assets/webhooks/roblox_logo_metal.png",
"text": "Roblox-Signature: UIe6GJ78MHCmU/zUKBYP3LV0lAqwWRFR6UEfPt1xBFw=, Zaman Damgası: 1683927229"
}
}
]
}
©2026 Roblox Corporation. Roblox, the Roblox logo and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.