Buat chatbot untuk ruang obrolan Stack Exchange

39

Tantangan

Tujuan dari tantangan ini adalah untuk membuat chatbot yang dapat berjalan di chatroom Stack Exchange. Bot Anda harus dapat mendeteksi kapan perintah spesifik diposting oleh pengguna dan menanggapinya. Ini adalah daftar perintah, dan apa yang harus dilakukan bot Anda:

  • !!newest: output judul (tanpa tautan, tetapi judul) dari pertanyaan terbaru yang diposting di situs ini (codegolf.SE).
  • !!metanewest: output judul pertanyaan terbaru yang diposting di situs meta (meta.codegolf.SE).
  • !!questioncount: output jumlah pertanyaan saat ini.
  • !!metaquestioncount: menampilkan jumlah pertanyaan saat ini di situs meta.
  • !!tag tagname: output kutipan tag (deskripsi singkat) dari tag yang diberikan sebagai parameter pertama.
  • !!metatag tagname: sama seperti di atas, tetapi untuk situs meta.
  • !!featured: menampilkan hitungan pertanyaan yang saat ini memiliki karunia.
  • !!metafeatured: menampilkan hitungan pertanyaan yang memiliki tag [fitur] di Meta.

Aturan

  1. Anda harus menulis program yang lengkap, bukan cuplikan atau fungsi.
  2. Jika perlu, Anda dapat meminta nama pengguna dan kata sandi sebagai input (meminta input, STDIN, argumen baris perintah). Ini akan diperlukan jika Anda menggunakan, misalnya, Python atau Ruby, tetapi tidak perlu jika Anda menggunakan JavaScript dan menjalankan skrip di halaman ruang obrolan itu sendiri.
  3. Anda diizinkan menggunakan perpustakaan eksternal untuk melakukan hal-hal seperti WebSockets. Perpustakaan ini tidak harus menghitung untuk jumlah karakter Anda.
  4. Anda dapat menggunakan bungkus obrolan eksternal (tetapi Anda tidak harus, menulis sendiri milik Anda), dan kemudian itu harus dihitung untuk jumlah karakter. Anda juga tidak diperbolehkan mengubah kode pembungkus. Jika Anda menggunakannya, Anda menggunakannya tanpa modifikasi dan semua karakter harus dihitung (itu sebagai hukuman karena tidak menulis bungkus Anda sendiri).

    Hanya kode bungkus itu sendiri yang harus dihitung. Jika ada file lain seperti contoh, ini tidak harus dihitung.

  5. Tidak ada penggunaan penyingkat URL atau cara lain yang dapat membuat URL lebih pendek: tantangannya adalah untuk golf chatbot, bukan untuk golf URL.
  6. Tidak ada permintaan web, kecuali yang diperlukan untuk mengobrol dan mendapatkan informasi yang diperlukan untuk menanggapi perintah.
  7. Penggunaan "celah" Standar tidak diperbolehkan.
  8. Jika seseorang pos komando, Anda perlu merespon dengan pesan chat dari format ini: @user response. Jadi, jika saya menulis perintah !!featureddan ada 5 pertanyaan utama, bot Anda harus dikirim @ProgramFOX 5.
  9. Jika saya menguji bot Anda, saya akan menjalankannya dari akun chatbot saya dan saya akan menjalankannya di chatroom ini . Saya akan selalu menguji bot di ruangan itu, jadi tidak perlu memberikan ID kamar sebagai input, itu akan selalu 14697. ID ini tidak akan diberikan sebagai input, itu harus hard-coded.
  10. Jika perintah tidak ditemukan, output @user The command [command] does not exist. Ganti [command]dengan nama perintah yang tidak ada. Jika argumen disediakan untuk perintah, jangan tampilkan argumen, hanya nama perintah.
  11. Jika suatu perintah memiliki banyak argumen, abaikan argumen yang tidak perlu.
  12. Jika suatu perintah tidak memiliki cukup argumen, keluaran @user You have not provided enough arguments
  13. Sistem mencegah pesan duplikat diposting dalam rentang waktu singkat. Jadi, saat menguji bot Anda, saya tidak akan pernah menjalankan dua perintah yang memberikan output yang sama secara berurutan (yang berarti bahwa Anda tidak harus mengimplementasikan sistem yang membuat pesan berbeda jika duplikat, dengan menambahkan titik misalnya).
  14. Sistem mencegah terlalu banyak pesan yang diposting dalam rentang waktu singkat, jadi saat pengujian, saya tidak akan pernah mengirim terlalu banyak perintah dalam rentang waktu singkat, yang berarti bahwa bot Anda tidak harus mengurus ini (dengan menunggu beberapa saat) sebelum memposting, misalnya).
  15. Ini adalah , program dengan jumlah byte terkecil yang menang.

Mulai

Berikut adalah beberapa info untuk memulai menulis bot Anda. Anda tidak harus menggunakan ini, tetapi ini bisa menjadi panduan.

  • Untuk masuk, pertama masuk ke penyedia OpenID. Ini akan selalu menjadi Stack Exchange OpenID ( https://openid.stackexchange.com). Formulir login terletak di https://openid.stackexchange.com/account/login, dan berikan nama pengguna dan kata sandi di sana.
  • Lalu, masuk ke stackexchange.com. Formulir login terletak di https://stackexchange.com/users/login. Pilih Stack Exchange sebagai penyedia OpenID.
  • Setelah melakukan itu, masuk untuk mengobrol. Formulir masuk untuk yang terletak di http://stackexchange.com/users/chat-login. Pilih Stack Exchange sebagai penyedia OpenID.
  • Maka Anda harus mendapatkan fkey. Untuk itu, buka http://chat.stackexchange.com/chats/join/favoritedan dapatkan fkeydari bidang input tersembunyi.
  • Untuk mengirim pesan, kirim permintaan ke http://chat.stackexchange.com/chats/14697/messages/new, dan berikan dua parameter POST: textparameter yang berisi teks pesan, dan fkeyparameter yang berisi fkey.
  • Untuk melihat kapan pesan baru diposting, Anda dapat menggunakan WebSockets (tetapi tidak harus, jangan ragu untuk menggunakan sesuatu yang lain jika lebih pendek). Silakan lihat jawaban Meta Stack Exchange ini :

    Obrolan

    (wss://chat.sockets.stackexchange.com/events/<roomnumber>/<somehash>?l=<timethingy>)

    Hash dapat diambil dengan POSTing id dan fkey kamar http://chat.stackexchange.com/ws-auth

    Ketepatan waktu adalah kunci waktu dari json yang dikembalikan oleh /chats/<roomno>/events.

    ID acara saat pesan diposting adalah 1.

  • Sangat berguna untuk melihat pembungkus obrolan yang ada, seperti Doorknob's StackExchange-Chatty dan Manishearth's ChatExchange , untuk melihat bagaimana cara kerjanya.
ProgramFOX
sumber
3
Saat saya melihat judulnya, saya langsung berpikir "ah, ProgramFOX".
seequ
Saya berharap metafeaturedakan berarti pertanyaan pada meta, tapi ... terima kasih :-)
John Dvorak
@JanDvorak Metas per-situs tidak memiliki hadiah, jadi saya tidak bisa menggunakannya. Ketika saya menulis tantangan ini, saya lupa bahwa Meta memiliki tag [fitur], jadi terima kasih atas saran Anda!
ProgramFOX
Apa yang saya lakukan untuk melihat apakah pesan baru diposting adalah memeriksa setiap 2 detik melalui JS jika pesan terakhir bukan oleh saya (item terakhir di kelas)
Cilan
Kami sudah punya satu di sini
Tn. Alien

Jawaban:

14

JavaScript + jQuery, 1362 1258 byte

Golf menggunakan minifier:

$(function(){function e(){function e(e,t){$("#input").val("@"+$(e).parents(".user-container").find(".username").eq(0).text()+" "+t),$("#sayit-button").click()}var i,a=$(t),s=a.map(function(e,t){return t.id}),r=s.slice(-1)[0]
n!=r&&(i=a.slice($.inArray(n,s)+1),n=r,i.map(function(t,n){var i,a,s,r,o,u,c,f=n.textContent.match(/!!(\S+)(?:\s+(\S+))?/)
if(f){switch(i=f[1],a=f[2],s="codegolf",0==i.indexOf("meta")&&(s="meta."+s,i=i.slice(4)),r="?site="+s,c=0,i){case"newest":o=["questions","&order=desc&sort=creation"],u=function(e){return e.items[0].title}
break
case"questioncount":o=["info",""],u=function(e){return e.items[0].total_questions}
break
case"tag":if(!a){c=1
break}o=["tags/"+a+"/wikis",""],u=function(e){return 0==e.items.length?"Tag not found":e.items[0].excerpt}
break
case"featured":o=0==s.indexOf("meta.")?["questions","&tagged=featured"]:["questions/featured",""],u=function(e){var t=e.items.length
return(e.items.has_more?"more than ":"")+t}}c?e(n,"You have not provided enough arguments"):o?$.get("http://api.stackexchange.com/2.2/"+o[0]+r+o[1],function(t){e(n,u(t))}):e(n,"The command "+i+" does not exist")}}))}var t="[id^=message-]",n=$(t).eq(-1).attr("id")
new MutationObserver(e).observe($("#chat").get(0),{childList:!0,subtree:!0})})

Anda harus menjalankan skrip langsung di browser (menggunakan karya jQuery Stack Exchange):

  1. Buka http://chat.stackexchange.com/rooms/14697/chatbot-challenge-on-programming-puzzles-code-golf
  2. Rekatkan kode di atas di konsol
  3. Masukkan beberapa perintah dalam obrolan

Bisa bermain golf lebih banyak, tetapi tidak bisa diganggu.


Tidak golf:

$(function() {
    var sel = '[id^=message-]';
    var latestMessage = $(sel).eq(-1).attr('id');
    function update() {
        var messages = $(sel);
        var ids = messages.map(function(i, x) { return x.id; });
        var newest = ids.slice(-1)[0];
        if(latestMessage == newest) {
            return;
        }
        var newMessages = messages.slice($.inArray(latestMessage, ids) + 1);
        latestMessage = newest;
        newMessages.map(function(i, x) {
            var m = x.textContent.match(/!!(\S+)(?:\s+(\S+))?/);
            if(!m) {
                return;
            }
            var c = m[1];
            var a = m[2];
            var s = 'codegolf';
            if(c.indexOf('meta') == 0) {
                s = 'meta.' + s;
                c = c.slice(4);
            }
            var site = '?site=' + s;
            var url;
            var extractor;
            var too_few_args = 0;
            switch(c) {
                case 'newest':
                    var url = ['questions', '&order=desc&sort=creation'];
                    extractor = function(data) {
                        return data.items[0].title;
                    };
                    break;
                case 'questioncount':
                    url = ['info', ''];
                    extractor = function(data) {
                        return data.items[0].total_questions;
                    };
                    break;
                case 'tag':
                    if(!a) {
                        too_few_args = 1;
                        break;
                    }
                    url = ['tags/' + a + '/wikis', ''];
                    extractor = function(data) {
                        if(data.items.length == 0) {
                            return 'Tag not found';
                        }
                        return data.items[0].excerpt;
                    };
                    break;
                case 'featured':
                    url = s.indexOf('meta.') == 0? ['questions', '&tagged=featured']: ['questions/featured', ''];
                    extractor = function(data) {
                        var l = data.items.length;
                        return (data.items.has_more? 'more than ': '') + l;
                    }
                    break;
            }
            if(too_few_args) {
                write(x, 'You have not provided enough arguments');
            } else if(!url) {
                write(x, 'The command ' + c + ' does not exist');
            } else {
                $.get('http://api.stackexchange.com/2.2/' + url[0] + site + url[1], function(data) {
                    write(x, extractor(data));
                });
            }
        });

        function write(x, m) {
            $('#input').val('@' + $(x).parents('.user-container').find('.username').eq(0).text() + ' ' + m);
            $('#sayit-button').click();
        }
    }
    new MutationObserver(update).observe($('#chat').get(0), {childList: true, subtree: true});
});
Tyilo
sumber
Bagus, terima kasih telah mengirim jawaban di sini! Saya sekarang akan menjalankan tes di ruangan. Bagaimanapun, saya pikir Anda dapat menyimpan beberapa karakter dengan menggunakan lebih banyak variabel satu huruf dan menghindari updatedan latestMessage.
ProgramFOX
Besar! Anda lulus semua tes . Satu-satunya hal aneh yang saya perhatikan adalah bot Anda mengembalikan hitungan pertanyaan yang berbeda dari pada beranda, tetapi saya melihat bahwa API mengembalikan nomor itu, jadi saya melaporkan ini di Meta dan menandai kotak uji sebagai yang benar. Sudah selesai dilakukan dengan baik! +1
ProgramFOX
Saya melihat Anda membuat bot lebih pendek. Bagus! :) Saya mengujinya kembali dan Anda masih lulus semua tes.
ProgramFOX
Agak terlambat, tapi saya baru saja menemukan peningkatan satu-arang: Anda dapat menggantinya 0==e.items.lengthdengan 1>e.items.lengthkarena panjangnya tidak akan pernah di bawah nol.
ProgramFOX