Stack Exchangeチャットルーム用のチャットボットを作成する


39

チャレンジ

この課題の目標は、Stack Exchangeのチャットルームで実行できるチャットボットを作成することです。ボットは、特定のコマンドがユーザーによって投稿されたときにそれを検出し、それに応答できる必要があります。これはコマンドのリストであり、ボットが行うべきことです:

  • !!newest:このサイト(codegolf.SE)に投稿された最新の質問のタイトル(リンクではなくタイトル)を出力します。
  • !!metanewest:メタサイト(meta.codegolf.SE)に投稿された最新の質問のタイトルを出力します。
  • !!questioncount:現在の質問数を出力します。
  • !!metaquestioncount:メタサイトで現在の質問数を出力します。
  • !!tag tagname:最初のパラメーターとして指定されたタグの抜粋(短い説明)を出力します。
  • !!metatag tagname:上記と同じですが、メタサイト用です。
  • !!featured:現在賞金がある質問の数を出力します。
  • !!metafeatured:Metaに[featured]タグがある質問の数を出力します。

ルール

  1. スニペットや関数ではなく、完全なプログラムを作成する必要があります。
  2. 必要な場合は、入力としてユーザー名とパスワードを要求できます(入力、STDIN、コマンドライン引数の入力を求めます)。これは、たとえばPythonやRubyを使用する場合に必要になりますが、JavaScriptを使用してチャットルームページ自体でスクリプトを実行する場合には必要ありません。
  3. 外部ライブラリを使用して、WebSocketのようなことを行うことができます。これらのライブラリは、文字数をカウントする必要はありません。
  4. あなたは、することができます(ただし、あなたが、あなた自身を書くことが奨励されている必要はありません)、外部チャットラッパーを使用して、文字カウントにカウントするように持っています。また、ラッパーのコードを変更することもできません。使用する場合は、変更せずに使用し、すべての文字をカウントする必要があります(独自のラッパーを作成しない場合のペナルティとして)。

    ラッパー自体のコードのみが重要です。例などの他のファイルがある場合、これらはカウントする必要はありません。

  5. URL短縮サービスやURLを短くする他の方法を使用しません。チャレンジはURLをゴルフするのではなく、チャットボットをゴルフすることです。
  6. チャットやコマンドへの応答に必要な情報の取得に必要なものを除き、Webリクエストはありません。
  7. 標準の「抜け穴」の使用は許可されていません。
  8. 誰かがコマンドを投稿した場合、次の形式のチャットメッセージで応答する必要があります@user response。したがって、コマンドを作成し、!!featured5つの注目すべき質問がある場合、ボットは投稿する必要があります@ProgramFOX 5
  9. ボットをテストする場合、チャットボットアカウントから実行し、このチャットルームで実行します。私は常にその部屋でボットをテストするので、部屋IDを入力として提供する必要はありません。常に14697です。このIDは入力として与えられないので、ハードコーディングする必要があります。
  10. コマンドが見つからない場合は、出力します@user The command [command] does not exist[command]存在しないコマンドの名前に置き換えます。引数がコマンドに提供されている場合、引数を出力せず、コマンド名のみを出力します。
  11. コマンドに多数の引数が必要な場合は、不要な引数を無視してください。
  12. コマンドに十分な引数がない場合、出力 @user You have not provided enough arguments
  13. システムは、重複したメッセージが短い時間範囲内に投稿されるのを防ぎます。したがって、ボットをテストするとき、同じ出力を連続して与える2つのコマンドを実行することはありません(つまり、たとえばドットを追加することで、メッセージが重複している場合にメッセージを変えるシステムを実装する必要はありません)。
  14. システムは、短い時間範囲内に投稿されるメッセージが多すぎることを防止するため、テスト時には、短い時間範囲内にあまり多くのコマンドを送信することはありません。つまり、ボットがこれを処理する必要はありません。たとえば、投稿する前に)。
  15. これはで、バイト数が最小のプログラムが勝ちます。

入門

ボットの作成を開始するための情報を次に示します。これを使用する必要はありませんが、ガイダンスになる可能性があります。

  • ログインするには、まずOpenIDプロバイダーにログインします。これは常にStack Exchange OpenID(https://openid.stackexchange.com)です。ログインフォームはにあり、https://openid.stackexchange.com/account/loginそこにユーザー名とパスワードを入力します。
  • 次に、にログインしstackexchange.comます。ログインフォームはにありますhttps://stackexchange.com/users/login。OpenIDプロバイダーとしてStack Exchangeを選択します。
  • その後、ログインしてチャットします。そのためのログインフォームはにありhttp://stackexchange.com/users/chat-loginます。OpenIDプロバイダーとしてStack Exchangeを選択します。
  • 次に、あなたが取得する必要がありますfkey。そのhttp://chat.stackexchange.com/chats/join/favoriteためにfkeyは、非表示の入力フィールドに移動して取得します。
  • メッセージを投稿するには、にリクエストを送信し、メッセージテキストを含むパラメーターとを含むhttp://chat.stackexchange.com/chats/14697/messages/newパラメーターという2つのPOSTパラメーターを提供textfkeyますfkey
  • 新しいメッセージがいつ投稿されたかを確認するには、WebSocketsを使用できます(ただし、短くする必要がある場合は自由に使用してください)。このMeta Stack Exchangeの回答をご覧ください:

    チャット

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

    ルームIDとfkeyをPOSTすることでハッシュを取得できます http://chat.stackexchange.com/ws-auth

    timethingyは、によって返されるjsonの時間キーです/chats/<roomno>/events

    メッセージが投稿されたときのイベントIDは1です。

  • DoorknobStackExchange-ChattyやManishearthのChatExchangeなどの既存のチャットラッパーを調べて、どのように機能するかを確認すると便利です。

3
タイトルを見た瞬間、すぐに「ああ、ProgramFOX」と思いました。
seequ 14年

私は期待していたmetafeaturedメタ上bountied質問を意味しますが...ありがとう:-)
ジョンドヴォルザーク

@JanDvorakサイトごとのメタには報奨金がないため、それを使用することはできません。このチャレンジを書いたとき、Metaに[featured]タグがあることを忘れていたので、ご提案ありがとうございます。
ProgramFOX 14年

私は新しいメッセージが投稿されたかどうかを確認するためにやったことは、最後のメッセージは私ではなかった場合はJSを経由して(クラスの最後の項目)を2秒ごとにチェックした
Cilan

回答:


14

JavaScript + jQuery、1362 1258バイト

ミニファイアーを使用したゴルフ:

$(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})})

ブラウザでスクリプトを直接実行する必要があります(Stack ExchangeのjQueryを使用)。

  1. http://chat.stackexchange.com/rooms/14697/chatbot-challenge-on-programming-puzzles-code-golfを開きます
  2. 上記のコードをコンソールに貼り付けます
  3. チャットにいくつかのコマンドを入力します

それはもっとたくさんゴルフすることができましたが、気にすることはできませんでした。


ゴルフをしていない:

$(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});
});

いいね、答えをここに投稿してくれてありがとう!次に、部屋でテストを実行します。とにかく、私はあなたがより多くの1文字の変数を使用してupdate、そして避けることによっていくつかのキャラクターを保存できると思うlatestMessage
ProgramFOX 14

すばらしいです!すべてのテストに合格しました。私が気づいた唯一の奇妙なことは、あなたのボットがホームページとは異なる質問数を返したことですが、APIがその数を返したのを見たので、メタでこれを報告し、テストケースを正しいとマークしました。よくやった!+1
ProgramFOX 14

ボットを短くしたのを見ました。いいね!:)私はそれを再テストしましたが、あなたはまだすべてのテストに合格しています。
ProgramFOX 14

むしろ後半に、私はちょうど1-char型の改善を見つけた:あなたは置き換えることができる0==e.items.lengthとの1>e.items.length長さがゼロを下回ることはありませんので。
ProgramFOX
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.