Eggdrop

Eggdrop İçin Tcl Değişkenler, Listeler ve Diziler Rehberi

· Güncelleme: · 6 dk okuma

Eggdrop İçin Tcl Değişkenler, Listeler ve Diziler Rehberi
İçindekiler
  1. Değişkenler: set ve $
  2. Kapsam: global ve Prosedürler
  3. Listeler
  4. Kullanıcı Metnini Listeye Çevirmek: split ve join
  5. Diziler (Array)
  6. Sözlükler (dict)
  7. Verileri Kalıcı Hâle Getirmek
  8. Gerçek Bir Senaryo: Kanal Aktivite Sayacı
  9. Metin İşleme Komutları
  10. Sık Yapılan Hatalar
  11. Ad Alanları (namespace)
  12. Sonuç

Bir Eggdrop scripti yazarken er ya da geç veri saklamanız gerekir: Kullanıcıların puanları, bir kanalın son konusu, banlanmış kelimeler listesi, kimin en son ne zaman komut kullandığı... Bu verileri yönetmenin yolu Tcl'in değişkenleri, listeleri ve dizileridir. Bu rehberde Tcl değişkenler ve veri yapılarını Eggdrop scriptleri bağlamında anlatıyoruz.

Değişkenler: set ve $

Tcl'de değişken tanımlamak için set kullanılır, değerini okumak için başına $ konur:

set selam "Merhaba"
set sayi 42
putlog "$selam, sayi: $sayi"

Tcl'de her şey aslında bir metindir. 42 bir sayı gibi davranabilir ama içte metin olarak tutulur. Sayısal işlemler için expr kullanılır:

set toplam [expr {$sayi + 8}]
incr sayi
incr sayi 5

incr, bir sayıyı artırmanın kısa yoludur. expr içindeki ifadeyi süslü parantezle yazmak hem daha hızlıdır hem de güvenlik açısından önerilir.

Kapsam: global ve Prosedürler

Tcl'in yeni başlayanları en çok şaşırtan kuralı budur: Prosedürler kendi değişken alanına sahiptir. Dışarıda tanımlanan bir değişken prosedürün içinden doğrudan görülmez:

set kanal_mesaji "Hos geldiniz!"

proc karsila {nick uhost hand chan} {
  global kanal_mesaji
  puthelp "NOTICE $nick :$kanal_mesaji"
}

global satırı olmadan prosedür "can't read kanal_mesaji: no such variable" hatası verir. Eggdrop'un kendi değişkenleri de (örneğin botnick) prosedürlerde global botnick ile kullanılır. Bu hata, sık hatalar listemizin en üst sıralarındadır.

Listeler

Liste, sıralı elemanlardan oluşan bir veri yapısıdır. Eggdrop'ta kanal listeleri, kullanıcı listeleri ve kelime listeleri genellikle liste olarak tutulur.

set yasakli [list reklam spam bedava]
lappend yasakli kripto
llength $yasakli
lindex $yasakli 0
lsearch -nocase $yasakli "SPAM"
lsort $yasakli
KomutNe yapar?
listYeni bir liste oluşturur
lappendListeye eleman ekler
llengthEleman sayısını verir
lindexBelirli sıradaki elemanı verir (0'dan başlar)
lsearchElemanı arar, sırasını verir; yoksa -1
lsortListeyi sıralar
lrangeListenin bir bölümünü verir
lreplaceEleman değiştirir veya siler

Kullanıcı Metnini Listeye Çevirmek: split ve join

Kanaldan gelen metin ham bir metindir. Kelimelere ayırmak için split kullanın:

set kelimeler [split $text]
set ilk [lindex $kelimeler 0]
set geri_kalan [join [lrange $kelimeler 1 end]]

split metni boşluklardan bölerek güvenli bir listeye çevirir. join ise listeyi tekrar metne dönüştürür. Ham kullanıcı metnini split olmadan doğrudan lindex gibi liste komutlarına vermek, metin içindeki süslü parantez veya tırnak gibi karakterler nedeniyle hatalara, hatta güvenlik sorunlarına yol açabilir.

Örnek: Mesajda yasaklı kelime var mı?

proc yasak_kontrol {nick uhost hand chan text} {
  global yasakli
  foreach kelime [split [string tolower $text]] {
    if {[lsearch -exact $yasakli $kelime] != -1} {
      putkick $chan $nick "Yasakli kelime"
      return
    }
  }
}

Diziler (Array)

Dizi, anahtar-değer çiftlerinden oluşur. Her kullanıcı için ayrı bir değer saklamak gerektiğinde idealdir:

set puan(Ayse) 10
set puan(Burak) 7
incr puan(Ayse)
putlog "Ayse'nin puani: $puan(Ayse)"

Dizilerle çalışmak için yararlı komutlar:

info exists puan(Deniz)
array names puan
array size puan
unset puan(Burak)

info exists kontrolü önemlidir: Var olmayan bir dizi elemanını okumaya çalışmak hata verir. Bir kullanıcının puanını artırmadan önce kaydı olup olmadığını kontrol edin:

if {![info exists puan($nick)]} { set puan($nick) 0 }
incr puan($nick)

Nickler büyük-küçük harf farkı içerebileceği için anahtar olarak kullanmadan önce string tolower ile küçük harfe çevirmek tutarlılık sağlar.

Sözlükler (dict)

Güncel Tcl sürümleri, dizilere benzeyen ama bir değer gibi taşınabilen dict yapısını sunar:

set kullanici [dict create nick Ayse puan 10 seviye 2]
dict get $kullanici puan
dict set kullanici puan 11

Dict'ler, bir veri kümesini prosedürler arasında parametre olarak aktarmak veya dosyaya yazmak için kullanışlıdır.

Verileri Kalıcı Hâle Getirmek

Değişkenler bellekte tutulur; bot yeniden başladığında kaybolur. Puanlar veya istatistikler gibi kalıcı olması gereken verileri bir dosyaya yazmalısınız:

proc puan_kaydet {} {
  global puan
  set f [open "puanlar.txt" w]
  puts $f [array get puan]
  close $f
}

proc puan_yukle {} {
  global puan
  if {![file exists "puanlar.txt"]} { return }
  set f [open "puanlar.txt" r]
  array set puan [read $f]
  close $f
}

array get diziyi bir listeye, array set ise listeyi tekrar diziye dönüştürür. Kaydetme işlemini düzenli aralıklarla yapmak için timer ve utimer yazımızdaki zamanlayıcıları kullanabilirsiniz.

Gerçek Bir Senaryo: Kanal Aktivite Sayacı

Kanaldaki her kullanıcının kaç mesaj yazdığını sayan basit bir script düşünelim. Her mesajda pubm bind'i tetiklenir, kullanıcının küçük harfe çevrilmiş nicki anahtar olarak kullanılarak bir dizideki sayaç artırılır. Bir !enaktif komutu ise diziyi listeye çevirir, sayıya göre sıralar ve ilk beş kişiyi kanala yazar. Bot yeniden başlatıldığında verilerin kaybolmaması için her on dakikada bir dizi dosyaya kaydedilir, bot açılırken de dosyadan yüklenir. Bu küçük senaryo; değişkenleri, dizileri, listeleri, sıralamayı ve dosya işlemlerini bir arada kullandığı için Tcl öğrenmek isteyenler için harika bir alıştırmadır.

Metin İşleme Komutları

Değişkenlerle birlikte en çok kullanacağınız komut ailesi string komutlarıdır. Kullanıcı mesajlarını işlerken neredeyse her scriptte karşınıza çıkarlar:

KomutNe yapar?
string tolowerMetni küçük harfe çevirir
string toupperMetni büyük harfe çevirir
string lengthKarakter sayısını verir
string matchJoker karakterli eşleştirme yapar
string firstBir alt metnin ilk geçtiği yeri bulur
string rangeMetnin bir bölümünü keser
string trimBaştaki ve sondaki boşlukları siler
string mapMetindeki parçaları başka parçalarla değiştirir

Eggdrop ayrıca IRC'ye özgü bazı yardımcılar sunar. Örneğin nickleri karşılaştırırken IRC'nin büyük-küçük harf kurallarını dikkate alan karşılaştırma komutları ve kontrol karakterlerini (renk, kalın yazı gibi) metinden temizleyen fonksiyonlar bulunur. Kullandığınız sürümün belgesinde bu yardımcıları incelemeniz, tekerleği yeniden icat etmenizi önler.

Sık Yapılan Hatalar

Tcl ile yeni tanışanların en sık düştüğü tuzakları bir arada toplayalım. Birincisi, prosedür içinde global satırını unutmaktır; bu durumda dışarıdaki değişken yerine yeni ve boş bir yerel değişkenle çalışırsınız ve değişiklikler kaybolur. İkincisi, liste ile metni karıştırmaktır; ham kullanıcı metnini liste komutlarına vermek tırnak ve parantez içeren mesajlarda hataya yol açar. Üçüncüsü, var olmayan dizi elemanını okumaya çalışmaktır; her zaman önce info exists ile kontrol edin. Dördüncüsü, büyük-küçük harf tutarsızlığıdır; aynı kişinin nicki bir kez büyük, bir kez küçük harfle yazıldığında dizide iki ayrı kayıt oluşur. Beşincisi ise değişkenleri gereğinden fazla global yapmaktır; yalnızca gerçekten paylaşılması gereken verileri global tutun, geri kalanını prosedür içinde yerel bırakın.

Ad Alanları (namespace)

Script sayınız arttıkça değişken ve prosedür isimlerinin çakışma ihtimali yükselir. Tcl'in namespace özelliği, scriptinizin bütün değişkenlerini ve prosedürlerini kendine ait bir alana yerleştirmenizi sağlar. Böylece iki farklı script aynı isimde bir değişken kullansa bile birbirini etkilemez. Küçük scriptlerde basit bir önek yeterli olur, ancak büyük ve paylaşılacak scriptlerde namespace kullanmak profesyonel bir alışkanlıktır.

Sonuç

Değişkenler, listeler ve diziler Eggdrop scriptlerinin hafızasıdır. global kuralını unutmayın, kullanıcı metnini her zaman split ile işleyin, dizi elemanlarına erişmeden önce varlığını kontrol edin ve kalıcı verileri dosyaya kaydedin. Zamana bağlı işler için sıradaki rehberimiz timer ve utimer.

IRC sorunun mu var? Kanalda birlikte çözelim.

💬 Kanala Bağlan

Sıkça Sorulan Sorular

Prosedür içinde dışarıdaki değişkene neden erişemiyorum?

Tcl'de prosedürlerin kendi değişken alanı vardır. Dışarıdaki bir değişkeni kullanmak için prosedürün başında global komutuyla bildirmeniz gerekir.

Liste ile dizi arasındaki fark nedir?

Liste sıralı elemanlardan oluşur ve sırayla erişilir. Dizi (array) ise anahtar-değer çiftlerinden oluşur ve anahtarla erişilir.

Kullanıcıdan gelen metni neden split ile bölmeliyim?

Ham metin özel karakterler içerebilir ve liste komutlarında beklenmedik sonuçlar doğurabilir. split, metni güvenli bir listeye dönüştürür.