"
# ── Veritabanı ──────────────────────────────────────────────────────
fonksiyon hazirla(db):
veritabani.sqlite(db, "CREATE TABLE IF NOT EXISTS baglanti(kod TEXT PRIMARY KEY, adres TEXT NOT NULL, olusturma TEXT, tiklama INTEGER DEFAULT 0); CREATE TABLE IF NOT EXISTS tiklama(kod TEXT, zaman TEXT);")
# Satırları `|` ile ayrılmış sütunlara böler. Adres son sütundur ve
# kendi içinde `|` taşıyabilir → kalan parçalar geri birleştirilir.
fonksiyon satirlar(ham):
sonuc = []
eger ham == "":
don sonuc
dongu s icinde ham.bol("\n"):
sonuc.ekle(s)
don sonuc
fonksiyon son_sutun(parcalar, bas):
don parcalar.dilim(bas, parcalar.uzunluk() - bas).birlestir("|")
# ── Kısa kod ────────────────────────────────────────────────────────
fonksiyon yeni_kod():
kod = ""
dongu _ icinde 1..KOD_UZUNLUGU:
kod = kod + ALFABE.dilim(rastgele.sayi(0, ALFABE.uzunluk() - 1), 1)
don kod
fonksiyon kod_gecerli(k):
eger k.uzunluk() != KOD_UZUNLUGU:
don yanlis
dongu i icinde 0..k.uzunluk() - 1:
eger degil ALFABE.icerir(k.dilim(i, 1)):
don yanlis
don dogru
# Hedef adres yalnız http(s) olabilir: `javascript:` ya da `file:` ile
# başlayan bir "bağlantı" kısaltıcıyı saldırı aracına çevirirdi.
fonksiyon adres_dogrula(a):
eger a.uzunluk() > 2000:
don "adres çok uzun"
eger degil (a.ile_baslar("https://") veya a.ile_baslar("http://")):
don "adres http:// ya da https:// ile başlamalı"
eger a.icerir(" ") veya a.icerir("\n") veya a.icerir("\r") veya a.icerir("\t"):
don "adres boşluk içeremez"
eger a.uzunluk() < 12:
don "adres eksik görünüyor"
don ""
fonksiyon kaydet(db, adres):
kod = yeni_kod()
# Çakışma olasılığı çok düşük ama sıfır değil: boş kod bulana dek dene.
iken veritabani.sqlite(db, "SELECT count(*) FROM baglanti WHERE kod = ?", [kod]) != "0":
kod = yeni_kod()
veritabani.sqlite(db, "INSERT INTO baglanti(kod, adres, olusturma) VALUES (?, ?, ?)", [kod, adres, zaman.simdi()])
don kod
# Tanıtım verisi: ilk açılışta birkaç bağlantı ve geçmiş tıklamalar.
fonksiyon ornek_veri(db):
eger veritabani.sqlite(db, "SELECT count(*) FROM baglanti") != "0":
don 0
adresler = ["https://kabaforce.com", "https://dev.kabaforce.com/kabalang/", "https://forge.kabaforce.com/KabaLang/ornekler", "https://maps.kabaforce.com/?q=Galata+Kulesi", "https://dev.kabaforce.com/kabalang/kilavuz/12-web-uygulamasi"]
agirlik = [7, 11, 5, 3, 2]
dongu i icinde 0..adresler.uzunluk() - 1:
kod = kaydet(db, adresler[i])
veritabani.sqlite(db, "UPDATE baglanti SET olusturma = datetime('now', 'localtime', ?) WHERE kod = ?", ["-" + metin(7 + i) + " days", kod])
# Son yedi güne yayılmış tıklamalar.
dongu gun icinde 0..6:
adet = rastgele.sayi(0, agirlik[i])
dongu _ icinde 1..adet:
veritabani.sqlite(db, "INSERT INTO tiklama(kod, zaman) VALUES (?, datetime('now', 'localtime', ?))", [kod, "-" + metin(gun) + " days"])
veritabani.sqlite(db, "UPDATE baglanti SET tiklama = (SELECT count(*) FROM tiklama WHERE tiklama.kod = baglanti.kod) WHERE kod = ?", [kod])
don 1
hazirla(db)
ornek_veri(db)
# ── Sayfalar ────────────────────────────────────────────────────────
fonksiyon ana_sayfa(_istek):
toplam = veritabani.sqlite(db, "SELECT count(*) FROM baglanti")
tik = veritabani.sqlite(db, "SELECT coalesce(sum(tiklama), 0) FROM baglanti")
bugun = veritabani.sqlite(db, "SELECT count(*) FROM tiklama WHERE date(zaman) = date('now', 'localtime')")
g = "
Uzun bağlantılar, kısa ve ölçülebilir.
"
g = g + "
Bir adres yapıştırın; KabaLang ona kısa bir kod versin ve her tıklamayı saysın.
"
g = g + ""
g = g + ""
g = g + "
"
g = g + "
Bağlantı
" + toplam + "
"
g = g + "
Toplam tıklama
" + tik + "
"
g = g + "
Bugün
" + bugun + "
"
g = g + "
"
g = g + "
Kısa kod
Hedef
Tıklama
"
dongu s icinde satirlar(veritabani.sqlite(db, "SELECT kod, tiklama, adres FROM baglanti ORDER BY olusturma DESC LIMIT 12")):
p = s.bol("|")
kod = p[0]
# Kod yalnız ALFABE harflerinden oluşur → href içinde güvenli.
# Hedef adres kullanıcıdan geldi → yalnız METİN olarak, kaçırılarak basılır.
g = g + "
"
# Küçük bir istemci betiği: formu JSON API'ye gönderir.
g = g + ""
don web.html(sayfa("Kısalt · KabaLang", g))
fonksiyon kisalt_api(istek):
govde = istek.govde()
eger degil json.gecerli_mi(govde):
don web.json(json.uret({"hata": "gövde geçerli JSON değil"}), 400)
adres = json.al(govde, "adres").kirp()
sorun = adres_dogrula(adres)
eger sorun != "":
don web.json(json.uret({"hata": sorun}), 422)
kod = kaydet(db, adres)
don web.json(json.uret({"kod": kod, "kisa": "/k/" + kod, "adres": adres}), 201)
fonksiyon bulunamadi_sayfasi():
g = "
"
don web.html(sayfa("Bulunamadı · Kısalt", g), 404)
fonksiyon yonlendir(istek):
kod = istek.parametre("kod")
eger degil kod_gecerli(kod):
don bulunamadi_sayfasi()
adres = veritabani.sqlite(db, "SELECT adres FROM baglanti WHERE kod = ?", [kod])
eger adres == "":
don bulunamadi_sayfasi()
veritabani.sqlite(db, "INSERT INTO tiklama(kod, zaman) VALUES (?, datetime('now', 'localtime'))", [kod])
veritabani.sqlite(db, "UPDATE baglanti SET tiklama = tiklama + 1 WHERE kod = ?", [kod])
# Gerçek HTTP yönlendirmesi: 302 + Location başlığı.
don web.yanit("", 302).baslik("Location", adres)
# Son 7 günün tıklamalarını SVG çubuk grafiğe çevirir — tamamen sunucuda.
fonksiyon yedi_gun_svg(db, kod):
gunler = []
adetler = []
en_cok = 1
dongu i icinde 0..6:
geri = 6 - i
gun = veritabani.sqlite(db, "SELECT strftime('%d.%m', 'now', 'localtime', ?)", ["-" + metin(geri) + " days"])
adet = sayi(veritabani.sqlite(db, "SELECT count(*) FROM tiklama WHERE kod = ? AND date(zaman) = date('now', 'localtime', ?)", [kod, "-" + metin(geri) + " days"]))
gunler.ekle(gun)
adetler.ekle(adet)
eger adet > en_cok:
en_cok = adet
gen = 700
yuk = 220
cubuk = 64
aralik = 36
svg = ""
fonksiyon istatistik(istek):
kod = istek.parametre("kod")
eger degil kod_gecerli(kod):
don bulunamadi_sayfasi()
satir = veritabani.sqlite(db, "SELECT tiklama, olusturma, adres FROM baglanti WHERE kod = ?", [kod])
eger satir == "":
don bulunamadi_sayfasi()
p = satir.bol("|")
son = veritabani.sqlite(db, "SELECT coalesce(max(zaman), '—') FROM tiklama WHERE kod = ?", [kod])
g = "