[Question]
  [
### The challenge
The goal of this challenge is to create a chatbot that can run in the chatrooms of Stack Exchange. Your bot needs to be able to detect when specific commands are posted by a user and respond to it. This is the list of commands, and what your bot should do:
* `!!newest`: output the title (no link, but the title) of the newest question posted on this site (codegolf.SE).
* `!!metanewest`: output the title of the newest question posted on the meta site (meta.codegolf.SE).
* `!!questioncount`: output the current question count.
* `!!metaquestioncount`: output the current question count on the meta site.
* `!!tag tagname`: output the tag excerpt (the short description) of the tag that's given as the first parameter.
* `!!metatag tagname`: same as above, but for the meta site.
* `!!featured`: output the count of questions that currently have a bounty.
* `!!metafeatured`: output the count of questions that have the [[featured]](http://meta.codegolf.stackexchange.com/questions/tagged/featured) tag on Meta.
## Rules
1. You should write a complete program, not a snippet or function.
2. In case it's necessary, you can request username and password as input (prompting for input, STDIN, command-line arguments). This will be necessary if you use, for example, Python or Ruby, but it won't be necessary if you use JavaScript and run the script on the chat room page itself.
3. You are allowed to use external libraries to do stuff like WebSockets. These libraries do not have to count for your character count.
4. You *can* use an external chat wrapper (but you don't have to, writing your own is encouraged), and then that has to count for the character count. You also are not allowed to change the wrapper's code. If you use it, you use it without modifications and all characters have to be counted (that's as a penalty for not writing your own wrapper).
Only the code of the wrapper itself has to count. If there are other files such as examples, these don't have to count.
5. No use of URL shorteners or other ways that can make URLs shorter: the challenge is to golf a chatbot, not to golf a URL.
6. No web requests, except those necessary to chat and to get the information necessary to respond to the commands.
7. Use of the [Standard "loopholes"](http://meta.codegolf.stackexchange.com/q/1061/9275) is not allowed.
8. If someone posts a command, you need to respond with a chat message of this format: `@user response`. So, if I write the command `!!featured` and there are 5 featured questions, your bot should post `@ProgramFOX 5`.
9. If I test your bot, I'll run it from my [chatbot account](https://codegolf.stackexchange.com/users/21569/fox-9000) and I'll run it in [this chatroom](http://chat.stackexchange.com/rooms/14697/chatbot-challenge-on-programming-puzzles-code-golf). I will always test the bots in that room, so it is not necessary to provide room ID as input, it will always be 14697. This ID won't be given as input, it should be hard-coded.
10. If the command is not found, output `@user The command [command] does not exist`. Replace `[command]` by the name of the non-existing command. If arguments are provided to the command, don't output the arguments, only the command name.
11. If a command has to many arguments, ignore the arguments that are not necessary.
12. If a command has not enough arguments, output `@user You have not provided enough arguments`
13. The system prevents that duplicate messages are posted within a short time range. So, when testing your bot, I will never run two commands that give the same output successively (which means that you do not have to implement a system that makes messages different if they are duplicates, by adding a dot for example).
14. The system prevents that too many messages get posted within a short time range, so when testing, I will never send too many commands within a short time range, which means that your bot does not have to take care of this (by waiting some time before posting, for example).
15. This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), the program with the least amount of bytes wins.
## Getting started
Here is some info to get started with writing your bot. You don't have to use this, but it can be a guidance.
* To log in, first log in to an OpenID provider. This will always be Stack Exchange OpenID (`https://openid.stackexchange.com`). The login form is located at `https://openid.stackexchange.com/account/login`, and provide the username and password there.
* Then, login to `stackexchange.com`. The login form is located at `https://stackexchange.com/users/login`. Choose Stack Exchange as OpenID provider.
* After doing that, log in to chat. The login form for that is located at `http://stackexchange.com/users/chat-login`. Choose Stack Exchange as OpenID provider.
* Then you need to get your `fkey`. For that, go to `http://chat.stackexchange.com/chats/join/favorite` and get the `fkey` from an hidden input field.
* To post a message, send a request to `http://chat.stackexchange.com/chats/14697/messages/new`, and provide two POST parameters: a `text` parameter containing the message text, and a `fkey` parameter containing the `fkey`.
* To see when a new message is posted, you can use WebSockets (but don't have to, feel free to use something else if it's shorter). Please see [this Meta Stack Exchange answer](https://meta.stackexchange.com/a/218355/229438):
> 
> ### Chat
> 
> 
> `(wss://chat.sockets.stackexchange.com/events/<roomnumber>/<somehash>?l=<timethingy>)`
> 
> 
> The hash can be fetched by POSTing the room id and fkey to `http://chat.stackexchange.com/ws-auth`
> 
> 
> The timethingy is the time key of the json returned by `/chats/<roomno>/events`.
> 
> 
> 
The event ID when a message is posted is `1`.
* It is useful to look at the existing chat-wrappers, such as Doorknob's [StackExchange-Chatty](https://github.com/KeyboardFire/stackexchange-chatty) and Manishearth's [ChatExchange](https://github.com/Manishearth/ChatExchange), to see how it exactly works.
  
[Answer]
# JavaScript + jQuery, ~~1362~~ 1258 bytes
Golfed using a 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})})
```
You have to run the script directly in the browser (using Stack Exchange's jQuery works):
1. Open <http://chat.stackexchange.com/rooms/14697/chatbot-challenge-on-programming-puzzles-code-golf>
2. Paste the above code in the console
3. Enter some commands in the chat
It could be golfed a lot more, but couldn't be bothered.
---
Un-golfed:
```
$(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});
});
```
]