maiden adalah kumpulan sistem untuk membantu Anda membangun aplikasi dan perpustakaan yang berinteraksi dengan server obrolan. Ini dapat membantu Anda membuat bot obrolan, atau klien obrolan umum. Ia juga menawarkan berbagai bagian yang akan mempermudah penulisan klien untuk protokol obrolan baru.
Jika Anda hanya ingin menggunakan maiden untuk menyiapkan bot, langkah-langkah untuk melakukannya cukup mudah. Pertama kita ingin memuat maiden dan semua modul dan komponen yang ingin Anda gunakan di bot Anda.
(ql:quickload '( maiden maiden -irc maiden -commands maiden -silly))
Lalu kita akan membuat inti dengan contoh konsumen yang ditambahkan ke dalamnya sesuai keinginan kita.
(defvar *core* ( maiden :make-core
'(: maiden -irc :nickname " maiden Test" :host "irc.freenode.net" :channels ("##testing"))
: maiden -commands
: maiden -silly))
Perintah make-core mengambil nama paket (sebagai string atau simbol) konsumen untuk ditambahkan, atau nama kelas langsung konsumen. Dalam kasus pertama, ia akan mencoba mencari sendiri nama kelas konsumen yang sesuai.
Dan itu saja. make-core
akan membuat inti, membuat instance semua konsumen, menambahkan mereka ke dalamnya, dan memulai semuanya. Sejumlah modul yang disediakan untuk maiden akan menggunakan semacam konfigurasi atau penyimpanan persisten. Untuk pengelolaannya, lihat subsistem penyimpanan.
Untuk menggunakan maiden sebagai kerangka kerja, pertama-tama Anda harus mendefinisikan sistem Anda sendiri dan mengemasnya seperti biasa untuk sebuah proyek. Untuk saat ini kita hanya akan menggunakan paket maiden -user
untuk bermain-main. Selanjutnya kita ingin mendefinisikan konsumen. Ini dapat dilakukan dengan define-consumer
.
(in-package #: maiden -user)
(define-consumer ping-notifier (agent)
())
Biasanya Anda ingin mendefinisikan agen. Agen hanya bisa ada satu kali pada sebuah inti. Kita akan membahas contoh untuk klien nanti. Sekarang, mulai saat ini kita dapat mendefinisikan metode dan fungsi kita sendiri yang mengkhususkan atau bertindak pada kelas konsumen seperti yang biasa Anda lakukan pada pemrograman CLOS secara umum. Selanjutnya, kita akan menentukan event kita sendiri yang akan kita gunakan untuk mengirim "permintaan ping" ke sistem.
(define-event ping (passive-event)
())
Peristiwa ini didefinisikan sebagai passive-event
karena tidak secara langsung meminta tindakan untuk diambil, namun menginformasikan sistem tentang ping yang sedang terjadi. Sekarang, untuk benar-benar membuat konsumen berinteraksi dengan sistem kejadian, kami juga ingin mendefinisikan penangan. Hal ini dapat dilakukan dengan define-handler
.
(define-handler (ping-notifier ping-receiver ping) (c ev)
(v:info :ping "Received a ping: ~a" ev))
Ini mendefinisikan sebuah pengendali yang disebut ping-receiver
pada konsumen ping-notifier
kita. Ini juga menentukan bahwa ia akan mendengarkan kejadian bertipe ping
. Arglist setelahnya mengatakan bahwa instance konsumen terikat ke c
dan instance event ke ev
. Badan kemudian mencatat pesan informasi menggunakan Verbose.
Mari kita uji ini dengan sangat cepat.
(defvar *core* (make-core 'ping-notifier))
(do-issue *core* ping)
Itu akan mencetak pesan status ke REPL seperti yang diharapkan. Dan itu adalah hal terpenting dalam menggunakan sistem ini. Perhatikan bahwa untuk melakukan hal-hal yang benar-benar berguna, Anda mungkin ingin menggunakan beberapa subsistem yang sudah ada sebelumnya yang diberikan oleh proyek maiden selain dari subsistem inti. Itu akan membantu Anda dengan pengguna, saluran, akun, perintah, jaringan, penyimpanan, dan sebagainya. Ingatlah juga bahwa Anda juga dapat menggunakan fitur-fitur yang ditawarkan Deeds, seperti memfilter ekspresi untuk penangan.
Sekarang mari kita lihat jenis klien primitif. Klien hanya dapat menulis ke file melalui acara.
(define-consumer file-client (client)
((file :initarg :file :accessor file))
(:default-initargs :file (error "FILE required.")))
(define-event write-event (client-event active-event)
((sequence :initarg :sequence))
(:default-initargs :sequence (error "SEQUENCE required.")))
Kami telah menjadikan write-event
sebagai client-event
karena harus spesifik untuk klien yang ingin kami kirimi surat, dan kami menjadikannya active-event
karena meminta sesuatu untuk terjadi. Sekarang mari kita tentukan handler kita yang akan menangani penulisan urutan ke file.
(define-handler (file-client writer write-event) (c ev sequence)
:match-consumer 'client
(with-open-file (stream (file c) :direction :output :if-exists :append :if-does-not-exist :create)
(write-sequence sequence stream)))
Opsi :match-consumer
memodifikasi filter handler sedemikian rupa sehingga filter hanya akan meneruskan peristiwa yang slot client
berisi instance file-client
yang sama dengan instance handler saat ini. Hal ini penting, karena setiap instance file-client
akan menerima instance penangannya sendiri pada sebuah inti. Tanpa opsi ini, write-event
akan ditangani oleh setiap contoh file-client
apa pun contoh acara tersebut dimaksudkan. Perhatikan juga bahwa kami menambahkan argumen sequence
ke daftar argumen handler. Argumen ini akan diisi dengan slot yang sesuai dari acara tersebut. Jika tidak ada slot seperti itu yang dapat ditemukan, maka ada sinyal kesalahan.
Saatnya untuk mengujinya. Kami hanya akan menggunakan kembali inti dari atas.
(add-to-core *core* '(file-client :file "~/foo" :name :foo)
'(file-client :file "~/bar" :name :bar))
(do-issue *core* write-event :sequence "foo" :client (consumer :foo *core*))
(do-issue *core* write-event :sequence "bar" :client (consumer :bar *core*))
(alexandria:read-file-into-string "~/foo") ; => "foo"
(alexandria:read-file-into-string "~/bar") ; => "bar"
Seperti yang Anda lihat, kejadian diarahkan ke instance handler yang sesuai dengan klien yang kita inginkan, dan file tersebut berisi apa yang kita harapkan.
Terakhir, perlu disebutkan bahwa dimungkinkan juga untuk menambah dan menghapus penangan secara dinamis saat runtime, dan bahkan melakukannya untuk penangan yang tidak terkait dengan konsumen tertentu. Hal ini sering berguna ketika Anda perlu menunggu respon dari suatu tempat. Untuk menangani logika melakukan hal ini secara asinkron dan mempertahankan kesan aliran imperatif, maiden menawarkan --seperti yang dilakukan Deeds-- makro with-awaiting
. Ini dapat digunakan sebagai berikut:
(with-awaiting (core event-type) (ev some-field)
(do-issue core initiating-event)
:timeout 20
some-field)
with-awaiting
sangat mirip dengan define-handler
, dengan pengecualian bahwa ia tidak memerlukan nama, dan sebagai pengganti nama konsumen di awal, ia memerlukan instance inti atau konsumen. Ini juga memerlukan satu opsi tambahan yang tidak digunakan, yaitu :timeout
. Tambahan lain yang diperlukan adalah "formulir pengaturan" setelah arglist. Untuk mengelola semuanya dengan benar dan memastikan tidak ada kondisi balapan yang mungkin terjadi di sistem, Anda harus memulai proses yang akan memicu peristiwa respons pada akhirnya di formulir pengaturan ini. Jika Anda memulainya sebelum waktu tersebut, kejadian respons mungkin dikirim sebelum pengendali sementara diatur dalam sistem dan akan tampak seolah-olah tidak pernah sampai sama sekali.
Dan itu hampir semua hal mendasarnya. Seperti disebutkan di atas, lihatlah subsistem yang termasuk dalam proyek ini, karena mereka akan membantu Anda dengan segala macam tugas dan masalah umum seputar sistem obrolan dan sebagainya.
Sebelum memahami maiden , ada baiknya memahami Perbuatan, meski hanya pada tingkat permukaan. maiden membangunnya dengan cukup berat.
core
adalah bagian sentral dari konfigurasi maiden . Ia bertanggung jawab untuk mengelola dan mengatur komponen lain dari sistem. Anda dapat menjalankan beberapa inti secara bersamaan dalam gambar cadel yang sama, dan bahkan dapat berbagi komponen di antara inti tersebut.
Lebih khusus lagi, Core terdiri dari event-loop dan sekumpulan konsumen. Event-loop bertanggung jawab untuk mengirimkan event ke handler. Konsumen bertanggung jawab untuk melampirkan penangan ke loop peristiwa. Operasi yang kemungkinan besar ingin Anda lakukan pada sebuah inti adalah: mengeluarkan peristiwa ke dalamnya dengan issue
, menambahkan konsumen ke dalamnya dengan add-consumer
, atau menghapus konsumen dari inti dengan remove-consumer
.
Untuk memudahkan Anda membuat inti yang berguna dengan menambahkan konsumen ke dalamnya, Anda dapat menggunakan fungsi make-core
dan add-to-core
.
event
adalah objek yang merepresentasikan perubahan pada sistem. Peristiwa dapat digunakan untuk mewakili perubahan yang telah terjadi, atau untuk mewakili permintaan agar perubahan terjadi. Ini masing-masing disebut passive-event
dan active-event
.
Umumnya Anda akan menggunakan acara dengan cara berikut:
consumer
adalah kelas yang mewakili komponen dalam sistem. Setiap konsumen dapat memiliki banyak penangan yang terikat padanya, yang akan bereaksi terhadap kejadian dalam sistem. Konsumen datang dalam dua supertipe dasar, agent
dan client
. Agen adalah konsumen yang seharusnya hanya ada satu kali pada inti, karena mereka mengimplementasikan fungsionalitas yang tidak masuk akal untuk dimultipleks dengan cara tertentu. Klien di sisi lain mewakili semacam jembatan ke sistem luar, dan tentu saja harus diizinkan untuk memiliki banyak contoh pada inti yang sama.
Jadi mengembangkan serangkaian perintah atau semacam antarmuka mungkin akan mengarah ke agen, sedangkan berinteraksi dengan layanan seperti XMPP akan mengarah ke klien.
Mendefinisikan konsumen harus dilakukan dengan define-consumer
, yang mirip dengan defclass
standar, tetapi memastikan bahwa superclass dan metaclass sudah diatur dengan benar.
handler
adalah objek yang memiliki fungsi yang melakukan tindakan tertentu ketika peristiwa tertentu dikeluarkan ke inti. Setiap penangan terikat pada konsumen tertentu dan dihapus atau ditambahkan ke loop peristiwa inti ketika konsumen dihapus atau ditambahkan ke inti.
Definisi handler terjadi melalui salah satu dari define-handler
, define-function-handler
, define-instruction
, atau define-query
. Yang masing-masing secara berturut-turut mengembangkan yang terakhir untuk memberikan singkatan yang lebih luas untuk persyaratan umum. Perhatikan bahwa cara penangan menerima kejadiannya bisa berbeda. Lihat dokumentasi Akta untuk melihat kelas handler apa yang tersedia.
Termasuk dalam proyek maiden adalah beberapa subsistem yang memperluas fungsionalitas inti.
Proyek maiden juga mencakup beberapa klien standar yang dapat langsung digunakan.
Terakhir, proyek ini memiliki banyak modul agen yang menyediakan fungsionalitas yang berguna untuk membuat bot obrolan dan semacamnya. Mereka juga bisa langsung digunakan.