12

Screenshot

enter image description here

About

Oneboxing is when you post a link to a supported site on SE Chat and it automatically shows extra information. An example is when you post a link to a question in Chat and it converts to the title, start of the body and author.

However, the list of supported sites is short, and there are feature requests such as this and this (from 2011) for certain sites to be added, but they've gotten nowhere so far.

So, I've made a userscript that lets you (or others) to create 'plugins' for Chat Oneboxing.

Usage

Users:

  1. Install the userscript.
  2. Copy and paste a plugin that someone has made just above the -------------------------------- in the middle of the script. That's it!

Developers: It's really simple:

  1. Install the userscript (so you can make and test your plugin)
  2. Make a HTML string containing all the data you need (ie. your onebox). You would probably use a 3rd-party API to get any information you need for the onebox.

There are examples and notes about creating plugins in the answers below! :)

Download

You can install it from the GitHub repo.

You can also view the source at the GitHub repo.

If you make a plugin, please post it as an answer below, as I have done! :)

  • Can you do your magic to allow CORS? – Universal Electricity Oct 25 '15 at 16:06
  • @Yummy what do you mean?? – ᔕᖺᘎᕊ Oct 25 '15 at 16:18
  • I'm just kidding, I wanted to know if it allows CORS and bypasses the Same Origin Policy – Universal Electricity Oct 25 '15 at 16:45
  • @YummyUnicornRainbowTails oh lol - nope :( It's expected that you would probably use an API to get all your information! :) – ᔕᖺᘎᕊ Oct 25 '15 at 16:56
  • Haven't tested it yet, but a doubt: all interested users must have the userscript installed for this to work, or is it "universal"? IMHO, this is not clear in your description... Oh, yeah, do you know if I upvote all your 3 answers, serial vote script will get me? ;) – brasofilo Oct 27 '15 at 4:57
  • @brasofilo yes, this userscript must be installed -- I'll make that clear in a sec. And no problem -- just upvote the answer you like the most :P – ᔕᖺᘎᕊ Oct 27 '15 at 9:49
4

Notes

  1. All you need to do to add your own oneboxed site is add a function to the customSites object (ie. add a 'plugin' :)
  2. The function must be named as the URL you want to onebox (eg. SoundCloud -> soundcloud.com as the function name)
  3. The function must have the parameters link and $obj, in that order! link = the matched link; $obj = the message as a jQuery element
  4. If you want additional CSS (which is likely), you have 3 options (in order of preference):
    • Use GM_addStyle (requires adding // @grant GM_addStyle to the usersript metadata block at the top)
    • Add a CSS file by adding it to the head: $('head').append(''); - The URL could be a github file
    • Use inline style="" attributes for each element
  5. If you need to, you can make an extra function if things start getting complex :)

In its most basic form, a 'plugin' can look like:

customSites['customsite.com'] = function(link, $obj) { //all sites must have a function like this, with those parameters. Change the 'customsite.com' to whatever your desired URL is
    var template = "<div class='ob-container'>A onebox!</div>" // A HTML String (ie. your oneboxed div)
    $obj.html(template);
} 

But you probably want to use some sort of API to actually get the information!


An example -- oneboxing SoundCloud links

customSites['soundcloud.com'] = function(link, $obj) { //Example: Oneboxing SoundCloud links
    $('head').append('<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/shu8/SEChat-soundcloudOneboxer/master/style.css">'); //Some custom CSS as an external stylesheet
    var client_id = 'f557cccd917d8ff72fb731f9b6b3aee5'; //My client ID for the SoundCloud APi
    $.get("http://api.soundcloud.com/resolve?url="+link+"&client_id="+client_id, function(d) {  //Using the SoundCloud API
        //Get the desired information:
        var user_avatar_url = d.user.avatar_url;
        var username = d.user.username;
        var artwork_url = d.artwork_url;
        var title = d.title;
        var playback_count = d.playback_count;
        var genre = d.genre;
        var permalink = d.permalink_url;
        var tags = d.tag_list; 
        var desc = d.description;
        var track_no = d.id;

        //Make a string containing all the tags with enclosed spans
        var tagsList = '';
        if(tags.length) {
            tags=tags.match(/(?:[^\s"]+|"[^"]*")+/g); //http://stackoverflow.com/a/16261693/3541881
            for (var i=0; i<tags.length; i++) {
                tagsList += "<span class='tag'>"+tags[i].replace(/"/g, '')+"</span>";
            }
        }

        //Make a HTML string, with the contents of the desired onebox div:
        var template = "<div class='sc-onebox'> \
                                       <div class='info'>"+username+"</div> \
                                       <div class='title'><a href='"+permalink+"'>"+title+"</a></div> \
                                       <div class='main'> \
                                           <img src='"+(artwork_url ? artwork_url : user_avatar_url)+"' /> \
                                           <div class='tags'>"+(tagsList ? tagsList : "No tags")+"</div> \
                                           <br> \
                                           <div class='desc'>&nbsp;"+(desc ? desc : "There is no description for this item :(")+"</div> \
                                           <div class='player'><iframe width='100%' height='100' scrolling='no' frameborder='no' src='https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/"+track_no+"'></iframe></div> \
                                       </div> \
                                   </div>";
        $obj.html(template); //add the oneboxed div. Done!
    });
};

Results in:

2

Oneboxing arXiv links

customSites['arxiv.org'] = function(link, $obj) {
    $('head').append('<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/shu8/SE-Chat-Custom-Oneboxes/master/arxiv.css">');
    var id = link.split('/')[4];
    if (id.indexOf('pdf') > -1) {
        id = id.replace('.pdf', '');
    }
    $.get("http://export.arxiv.org/api/query?search_query="+id, function(d) {
        var $xml = $(d);
        console.log($xml);
        var title = $xml.find('entry title').text();
        var author = $xml.find('entry author').text();
        var summary = $xml.find('entry summary').text();
        var url = $xml.find('entry link[type="text/html"]').attr('href');

        var template = "<div class='arxiv-container'> \
                            <img src='http://i.stack.imgur.com/0h65A.jpg' /> \
                            <div class='title'><a href='"+url+"'>"+title+"</a></div> \
                            <div class='author'>"+author+"</div> \
                            <div class='desc'>"+summary+"</div> \
                        </div>";
        $obj.html(template);
    }); 
};
  • @E.P. sorry, my bad. It's been fixed in this answer now :) – ᔕᖺᘎᕊ Aug 12 '16 at 13:27
  • Cool =). Any chances we can tempt you into making a DOI oneboxer? – E.P. Aug 12 '16 at 13:33
  • @E.P. I'd be more than happy to -- few questions tho 1) who's 'we' :P 2) what's DOI? :/ and 3) do you have any thoughts on what the onebox could look like? – ᔕᖺᘎᕊ Aug 12 '16 at 13:34
  • DOIs are Digital Object Identifiers and they're the main ID of research papers, so you can link to, say, dx.doi.org/10.1088/0953-4075/48/15/151001, and it is the persistent identifier of the paper. It would be nice to get much the same information as in the arXiv onebox - title, authors, nicely-formatted bibliographic citation, abstract, and link to the paper. I'm not sure it's trivial, though. – E.P. Aug 12 '16 at 13:40
  • @E.P. ahh I remember looking into this once before (lol and forgot what they were :P) and the problem was that there isn't one single standard for every paper in the way that they give the DOI so it would have been incredibly unreliable :(. If there are specific sites for which you want the DOI for, that should be easier because each site has their own standard... – ᔕᖺᘎᕊ Aug 12 '16 at 13:43
  • Yeah, I imagine that's probably what'll happen. =|. – E.P. Aug 12 '16 at 13:45
  • @E.P. I know it's probably really annoying, but yeah, if there are a few main sites, I could look into that for you :) – ᔕᖺᘎᕊ Aug 12 '16 at 13:46
  • 1
    Nah, it's too big of an ask. I'll look into it when I have time ;-). – E.P. Aug 12 '16 at 13:48
1

Oneboxing Spotify Links

customSites['play.spotify.com'] = function(link, $obj) {
    $('head').append('<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/shu8/SE-Chat-Custom-Oneboxes/master/spotify.css">');
    if(link.indexOf('album') > -1) {
        var album_id = link.split('/')[4];
        $.get("https://api.spotify.com/v1/albums/"+album_id, function(d) {
            var url = d.external_urls.spotify;
            var image = d.images[0].url;
            var artist = d.artists[0].name;         
            var name = d.name;
            var type = d.type;

            var template = "<div class='spotify-container'> \
                                <img src='"+image+"'> \
                                <div class='info'>"+type+"</div> \
                                <div class='title'><a href='"+url+"'>"+name+"</a></div> \
                                <div class='artist'>"+artist+"</div> \
                            </div>";
            $obj.html(template);
        });
    } else if (link.indexOf('artist') > -1) {
        var artist_id = link.split('/')[4];
        $.get("https://api.spotify.com/v1/artists/"+artist_id, function(d) {
            var url = d.external_urls.spotify;
            var image = d.images[0].url;
            var name = d.name;
            var type = d.type;

            var template = "<div class='spotify-container'> \
                                <img src='"+image+"'> \
                                <div class='info'>"+type+"</div> \
                                <div class='title'><a href='"+url+"'>"+name+"</a></div> \
                            </div>";

            $obj.html(template);
        });     
    } else if (link.indexOf('track') > -1) {
        var track_id = link.split('/')[4];
        $.get("https://api.spotify.com/v1/tracks/"+track_id, function(d) {
            var url = d.external_urls.spotify;
            var name = d.name;
            var type = d.type;
            var artist = d.artists[0].name;

            var template = "<div class='spotify-container'> \
                                <img src='http://i.stack.imgur.com/yQJQ0.png'> \
                                <div class='info'>"+type+"</div> \
                                <div class='title'><a href='"+url+"'>"+name+"</a></div> \
                                <div class='artist'>"+artist+"</div> \
                            </div>";

            $obj.html(template);
        });         
    }   
};
1

Oneboxing links to Stack Exchange user profiles (the main site)

customSites['stackexchange.com'] = function(link, $obj) {
    if(link.indexOf('/users/') > -1) {
        var user_id = link.split('/')[4];
        $.getJSON("http://api.stackexchange.com/2.2/users/"+user_id+"/associated", function(json) {
            var oldestSiteUserId = json.items[0].user_id;
            var oldestSite = json.items[0].site_url.split('/')[2].split('.')[0];
            var oldestSiteRealName = json.items[0].site_name;

            $.getJSON("http://api.stackexchange.com/2.2/users/"+oldestSiteUserId+"?order=desc&sort=reputation&site="+oldestSite+"&filter=!9YdnSA07B", function(json2) {
                var display_name = json2.items[0].display_name,
                    location = json2.items[0].location,
                    image = json2.items[0].profile_image,
                    about = json2.items[0].about_me;
                var template = '<div class="onebox ob-user">\
                    <div class="user-gravatar64">\
                        <a href="http://stackexchange.com/users/'+user_id+'">\
                            <img height="64" width="64" alt="" src="'+image+'">\
                        </a>\
                    </div>\
                    <div>\
                        <img width="20" height="20" src="http://sstatic.net/stackexchange/img/apple-touch-icon.png" >\
                        <a class="ob-user-username" style="color: #4E82C2;" href="http://stackexchange.com/users/'+user_id+'">'+display_name+'</a>, '+location+'\
                    </div>\
                    <div style="overflow: auto;    height: 50px;">\
                        '+about+'\
                    </div>\
                 </div>';

                 $obj.html(template);                
            });
        });        
    }
};
1

Oneboxing Steam Store links

customSites['store.steampowered.com'] = function(link, $obj) { // http://store.steampowered.com/app/377840/
    $('head').append('<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/shu8/SE-Chat-Custom-Oneboxes/a043cfaae462d918f94558e188749089ef9d97cb/steam.css">');
    var id = link.split('/')[4];
    $.get("https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20json%20where%20url%3D%22"+encodeURIComponent('http://store.steampowered.com/api/appdetails?appids='+id)+"%22&format=json&diagnostics=true&callback=", function(d) {
        data = d.query.results['_'+id.slice(1)].data;  
        tags = '';
        $.each(data.categories, function() { tags += '<span class="ob-post-tag">' + $(this)[0].description + '</span>'; })
        var template = "<div class='steam-container'> \
                            <img src='"+data.header_image+"' /> \
                            <div class='title'><a href='"+link+"'>"+data.name+"</a></div> \
                            <div class='tags'>" + tags + "</div> \
                            <div class='desc'>"+data.short_description+"</div> \
                        </div>";
        $obj.html(template);
    }); 
};
  • 1
    Steam has updated their API to include the short_description, which is the text that appears beneath the header_image when viewing the store page for the game. This script should probably do the same (replacing about_the_game). CSS also looks to need updating as the header image takes up more vertical space than the text at some resolutions. – MBraedley May 14 '17 at 15:23
  • @MBraedley Thanks for the CSS fixes you did on github! :) I'll look into updating the short_description ASAP! :) I'm really sorry I took so long to respond! I've been really busy :( – ᔕᖺᘎᕊ May 25 '17 at 20:54
  • 1
    Just submitted an edit. Wasn't going to do it behind your back or anything. – MBraedley May 25 '17 at 21:02
  • @MBraedley Thanks! That was easier than I thought it would be :P thanks for all the changes you've made again :)) – ᔕᖺᘎᕊ May 25 '17 at 21:06
0

Oneboxing OEIS entries

customSites['oeis.org'] = function(link, $obj) {
    var id = link.split('/')[3];
    if(id) {
    $('head').append('<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/shu8/SE-Chat-Custom-Oneboxes/master/oeis.css">');
        $.get("https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodeURIComponent('http://oeis.org/' + id) + "%22&callback=", function(d) {
            var $document = $(d);
            var $table = $document.find('form').parent().next();
            var number = $table.find('table:eq(1) td:eq(0)').text().trim();
            var desc = $table.find('table:eq(1) td:eq(2)').text().trim();
            var sequence = $table.find('table:eq(2)').text().trim().replace(/ *\([^)]*\)/, ''); //http://stackoverflow.com/a/4292483/3541881
            var template = "<div class='oeis-container'>\
                              <span class='id'>[OEIS]: <a href='"+link+"'>"+number+"</a></span>\
                              <span>"+desc+"</span>\
                              <span class='sequence'>"+sequence.replace(/ *\([^)]*\)/, '')+"</span>\
                            </div>";
            $obj.html(template);
        });
    }
};
0

Oneboxing etymonline definitions

customSites['etymonline.com'] = function(link, $obj) {
    var term = link.split('?')[1].split('term=')[1];
    if(term) {
    $('head').append('<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/shu8/SE-Chat-Custom-Oneboxes/master/etymonline.css">');
        $.get("https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodeURIComponent('http://etymonline.com/index.php?term=' + term) + "%22&callback=", function(d) {
            var termToDisplay = $(d).find('#dictionary dt:eq(0)').text(),
                definition = $(d).find('#dictionary dd:eq(0)').text();

            var template = "<div class='etymonline-container'>\
                              <span class='term'>[etymonline]: <a href='"+link+"'>" + termToDisplay + "</a></span><br>\
                              <span>" + definition + "</span>\
                            </div>";

            $obj.html(template);
        });
    }
};

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .