CINXE.COM
What Really IRCs Me: Slack | Linux Journal
<!DOCTYPE html> <html lang="en" dir="ltr" prefix="content: http://purl.org/rss/1.0/modules/content/ dc: http://purl.org/dc/terms/ foaf: http://xmlns.com/foaf/0.1/ og: http://ogp.me/ns# rdfs: http://www.w3.org/2000/01/rdf-schema# schema: http://schema.org/ sioc: http://rdfs.org/sioc/ns# sioct: http://rdfs.org/sioc/types# skos: http://www.w3.org/2004/02/skos/core# xsd: http://www.w3.org/2001/XMLSchema# " class="no-js wf-loading"> <head> <meta charset="utf-8" /> <meta name="Generator" content="Drupal 9 (https://www.drupal.org)" /> <meta name="MobileOptimized" content="width" /> <meta name="HandheldFriendly" content="true" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="icon" href="/themes/linuxjournal/favicon.ico" type="image/vnd.microsoft.icon" /> <link rel="canonical" href="https://www.linuxjournal.com/content/what-really-ircs-me-slack" /> <link rel="shortlink" href="https://www.linuxjournal.com/node/1339928" /> <title>What Really IRCs Me: Slack | Linux Journal</title> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/align.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/fieldgroup.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/container-inline.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/clearfix.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/details.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/hidden.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/item-list.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/js.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/nowrap.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/position-container.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/progress.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/reset-appearance.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/resize.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/sticky-header.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/system-status-counter.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/system-status-report-counters.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/system-status-report-general-info.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/tablesort.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/system/css/components/tree-child.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/modules/contrib/poll/css/poll.base.css?snzigw" /> <link rel="stylesheet" media="all" href="/modules/contrib/poll/css/poll.theme.css?snzigw" /> <link rel="stylesheet" media="all" href="/core/modules/views/css/views.module.css?snzigw" /> <link rel="stylesheet" media="all" href="/libraries/shariff/shariff.complete.css?snzigw" /> <link rel="stylesheet" media="all" href="/modules/contrib/webform/modules/webform_bootstrap/css/webform_bootstrap.css?snzigw" /> <link rel="stylesheet" media="all" href="/themes/linuxjournal/css/style.css?snzigw" /> <link rel="stylesheet" media="all" href="/themes/linuxjournal/css/fonts.css?snzigw" /> <!-- <script defer src="https://use.fontawesome.com/releases/v5.0.9/js/all.js" integrity="sha384-8iPTk2s/jMVj81dnzb/iFR2sdA7u06vHJyyLlAd4snFpCl/SnyUjRrbdJsw1pGIl" crossorigin="anonymous"></script>--> <script> // Non-blocking webfonts. (function iife() { 'use strict'; // JS is able to start executing. document.documentElement.classList.remove('no-js'); // Optimization for Repeat Views // Stop early for repeat views that have already cached fonts. if (sessionStorage.fontsLoadedLateef && sessionStorage.fontsLoadedOpensans /* && sessionStorage.fontsLoadedNEWFONT */) { document.documentElement.classList.remove('wf-loading'); document.documentElement.classList.add('wf-opensans'); document.documentElement.classList.add('wf-lateef'); // document.documentElement.classList.add('wf-NEWFONT'); return; } // Inlined Font Face Observer script + Promise polyfill. /*! Font Face Observer v2.0.13 - © Bram Stein. License: BSD-3-Clause */ (function(){'use strict';var f,g=[];function l(a){g.push(a);1==g.length&&f()}function m(){for(;g.length;)g[0](),g.shift()}f=function(){setTimeout(m)};function n(a){this.a=p;this.b=void 0;this.f=[];var b=this;try{a(function(a){q(b,a)},function(a){r(b,a)})}catch(c){r(b,c)}}var p=2;function t(a){return new n(function(b,c){c(a)})}function u(a){return new n(function(b){b(a)})}function q(a,b){if(a.a==p){if(b==a)throw new TypeError;var c=!1;try{var d=b&&b.then;if(null!=b&&"object"==typeof b&&"function"==typeof d){d.call(b,function(b){c||q(a,b);c=!0},function(b){c||r(a,b);c=!0});return}}catch(e){c||r(a,e);return}a.a=0;a.b=b;v(a)}} function r(a,b){if(a.a==p){if(b==a)throw new TypeError;a.a=1;a.b=b;v(a)}}function v(a){l(function(){if(a.a!=p)for(;a.f.length;){var b=a.f.shift(),c=b[0],d=b[1],e=b[2],b=b[3];try{0==a.a?"function"==typeof c?e(c.call(void 0,a.b)):e(a.b):1==a.a&&("function"==typeof d?e(d.call(void 0,a.b)):b(a.b))}catch(h){b(h)}}})}n.prototype.g=function(a){return this.c(void 0,a)};n.prototype.c=function(a,b){var c=this;return new n(function(d,e){c.f.push([a,b,d,e]);v(c)})}; function w(a){return new n(function(b,c){function d(c){return function(d){h[c]=d;e+=1;e==a.length&&b(h)}}var e=0,h=[];0==a.length&&b(h);for(var k=0;k<a.length;k+=1)u(a[k]).c(d(k),c)})}function x(a){return new n(function(b,c){for(var d=0;d<a.length;d+=1)u(a[d]).c(b,c)})};window.Promise||(window.Promise=n,window.Promise.resolve=u,window.Promise.reject=t,window.Promise.race=x,window.Promise.all=w,window.Promise.prototype.then=n.prototype.c,window.Promise.prototype["catch"]=n.prototype.g);}()); (function(){function l(a,b){document.addEventListener?a.addEventListener("scroll",b,!1):a.attachEvent("scroll",b)}function m(a){document.body?a():document.addEventListener?document.addEventListener("DOMContentLoaded",function c(){document.removeEventListener("DOMContentLoaded",c);a()}):document.attachEvent("onreadystatechange",function k(){if("interactive"==document.readyState||"complete"==document.readyState)document.detachEvent("onreadystatechange",k),a()})};function r(a){this.a=document.createElement("div");this.a.setAttribute("aria-hidden","true");this.a.appendChild(document.createTextNode(a));this.b=document.createElement("span");this.c=document.createElement("span");this.h=document.createElement("span");this.f=document.createElement("span");this.g=-1;this.b.style.cssText="max-width:none;display:inline-block;position:absolute;height:100%;width:100%;overflow:scroll;font-size:16px;";this.c.style.cssText="max-width:none;display:inline-block;position:absolute;height:100%;width:100%;overflow:scroll;font-size:16px;"; this.f.style.cssText="max-width:none;display:inline-block;position:absolute;height:100%;width:100%;overflow:scroll;font-size:16px;";this.h.style.cssText="display:inline-block;width:200%;height:200%;font-size:16px;max-width:none;";this.b.appendChild(this.h);this.c.appendChild(this.f);this.a.appendChild(this.b);this.a.appendChild(this.c)} function t(a,b){a.a.style.cssText="max-width:none;min-width:20px;min-height:20px;display:inline-block;overflow:hidden;position:absolute;width:auto;margin:0;padding:0;top:-999px;white-space:nowrap;font-synthesis:none;font:"+b+";"}function y(a){var b=a.a.offsetWidth,c=b+100;a.f.style.width=c+"px";a.c.scrollLeft=c;a.b.scrollLeft=a.b.scrollWidth+100;return a.g!==b?(a.g=b,!0):!1}function z(a,b){function c(){var a=k;y(a)&&a.a.parentNode&&b(a.g)}var k=a;l(a.b,c);l(a.c,c);y(a)};function A(a,b){var c=b||{};this.family=a;this.style=c.style||"normal";this.weight=c.weight||"normal";this.stretch=c.stretch||"normal"}var B=null,C=null,E=null,F=null;function G(){if(null===C)if(J()&&/Apple/.test(window.navigator.vendor)){var a=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))(?:\.([0-9]+))/.exec(window.navigator.userAgent);C=!!a&&603>parseInt(a[1],10)}else C=!1;return C}function J(){null===F&&(F=!!document.fonts);return F} function K(){if(null===E){var a=document.createElement("div");try{a.style.font="condensed 100px sans-serif"}catch(b){}E=""!==a.style.font}return E}function L(a,b){return[a.style,a.weight,K()?a.stretch:"","100px",b].join(" ")} A.prototype.load=function(a,b){var c=this,k=a||"BESbswy",q=0,D=b||3E3,H=(new Date).getTime();return new Promise(function(a,b){if(J()&&!G()){var M=new Promise(function(a,b){function e(){(new Date).getTime()-H>=D?b():document.fonts.load(L(c,'"'+c.family+'"'),k).then(function(c){1<=c.length?a():setTimeout(e,25)},function(){b()})}e()}),N=new Promise(function(a,c){q=setTimeout(c,D)});Promise.race([N,M]).then(function(){clearTimeout(q);a(c)},function(){b(c)})}else m(function(){function u(){var b;if(b=-1!= f&&-1!=g||-1!=f&&-1!=h||-1!=g&&-1!=h)(b=f!=g&&f!=h&&g!=h)||(null===B&&(b=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(window.navigator.userAgent),B=!!b&&(536>parseInt(b[1],10)||536===parseInt(b[1],10)&&11>=parseInt(b[2],10))),b=B&&(f==v&&g==v&&h==v||f==w&&g==w&&h==w||f==x&&g==x&&h==x)),b=!b;b&&(d.parentNode&&d.parentNode.removeChild(d),clearTimeout(q),a(c))}function I(){if((new Date).getTime()-H>=D)d.parentNode&&d.parentNode.removeChild(d),b(c);else{var a=document.hidden;if(!0===a||void 0===a)f=e.a.offsetWidth, g=n.a.offsetWidth,h=p.a.offsetWidth,u();q=setTimeout(I,50)}}var e=new r(k),n=new r(k),p=new r(k),f=-1,g=-1,h=-1,v=-1,w=-1,x=-1,d=document.createElement("div");d.dir="ltr";t(e,L(c,"sans-serif"));t(n,L(c,"serif"));t(p,L(c,"monospace"));d.appendChild(e.a);d.appendChild(n.a);d.appendChild(p.a);document.body.appendChild(d);v=e.a.offsetWidth;w=n.a.offsetWidth;x=p.a.offsetWidth;I();z(e,function(a){f=a;u()});t(e,L(c,'"'+c.family+'",sans-serif'));z(n,function(a){g=a;u()});t(n,L(c,'"'+c.family+'",serif')); z(p,function(a){h=a;u()});t(p,L(c,'"'+c.family+'",monospace'))})})};"object"===typeof module?module.exports=A:(window.FontFaceObserver=A,window.FontFaceObserver.prototype.load=A.prototype.load);}()); // Load and observe Lateef var Lateef = new FontFaceObserver('Lateef', {weight: 400}); Promise.all([Lateef.load()]).then(function() { document.documentElement.classList.remove('wf-loading'); document.documentElement.classList.add('wf-lateef'); // Optimization for Repeat Views // Set a flag in localstorage so repeat views can skip processing FFO. sessionStorage.fontsLoadedLateef = true; }); // Load and observe Open Sans var os300 = new FontFaceObserver('Open Sans', {weight: 300}); var os400 = new FontFaceObserver('Open Sans', {weight: 400}); Promise.all([os300.load(), os400.load()]).then(function() { document.documentElement.classList.remove('wf-loading'); document.documentElement.classList.add('wf-opensans'); // Optimization for Repeat Views // Set a flag in localstorage so repeat views can skip processing FFO. sessionStorage.fontsLoadedOpensans = true; }); // Load and observe NEWFONT /* var NEWFONT = new FontFaceObserver('NEWFONT', {weight: 400}); Promise.all([NEWFONT.load()]).then(function() { document.documentElement.classList.remove('wf-loading'); document.documentElement.classList.add('wf-NEWFONT'); // Optimization for Repeat Views // Set a flag in localstorage so repeat views can skip processing FFO. sessionStorage.fontsLoadedNEWFONT = true; }); */ })(); </script> <script src="https://www.google.com/recaptcha/api.js" async defer></script> <script src=https://slashdot.org/country.js></script> <script src="/themes/linuxjournal/js/ada.js"></script> <script src="/themes/linuxjournal/js/accessibility.js"></script> <script>window.addEventListener('load', function() { new Accessibility(); });</script> <script src="//a.fsdn.com/con/js/sftheme/cmp2.js"></script> <link rel="stylesheet" href="//a.fsdn.com/con/css/sftheme/sandiego/cmp.css" type="text/css"> <link rel="stylesheet" href="/themes/linuxjournal/css/ccpa.css" type="text/css"> <script>window.bizx.cmp.init({ geo: window });</script> <script> function bm_trace() { (function (w,d,t) { _ml = w._ml || {}; _ml.eid = '771'; var s, cd, tag; s = d.getElementsByTagName(t)[0]; cd = new Date(); tag = d.createElement(t); tag.async = 1; tag.src = 'https://ml314.com/tag.aspx?' + cd.getDate() + cd.getMonth(); s.parentNode.insertBefore(tag, s); })(window,document,'script'); } bizx.cmp.ifConsent('', ['all', 'bombora'],bm_trace); </script> </head> <body class="path-node page-node-type-story has-glyphicons"> <a href="#main-content" class="visually-hidden focusable skip-link"> Skip to main content </a> <div class="dialog-off-canvas-main-canvas" data-off-canvas-main-canvas> <div id="wrap"> <div class="leader-wrapper" id="leader-wrapper"> </div> <div class="brand-wrapper" id="brand-wrapper"> <div class="brand container"> <div class="region region-brand"> <a class="logo navbar-btn" href="/" title="Home" rel="home"> <h1><img src="/themes/linuxjournal/images/ljlogo.png" alt="Linux Journal" /></h1> </a> <section id="block-topbannernearlogo" class="block block-block-content block-block-contenta8e75a3d-967c-416d-8944-4015d1f90a84 clearfix"> </section> </div> </div> <div class="header-wrapper"> <header class="navbar navbar-default container" id="navbar" role="banner"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <div id="navbar-collapse" class="navbar-collapse collapse"> <div class="region region-navigation-collapsible"> <section id="block-linuxjournal-main-menu" class="block block-system block-system-menu-blockmain clearfix navbar__menu col-xs-12 col-sm-8"> <ul class="menu menu--main nav navbar-nav"> <li class="expanded dropdown first"> <a href="/" class="dropdown-toggle" data-toggle="dropdown" data-drupal-link-system-path="<front>">Topics+ <span class="caret"></span></a> <ul class="dropdown-menu"> <li class="first"> <a href="/tag/cloud">Cloud</a> </li> <li> <a href="/tag/containers" data-drupal-link-system-path="taxonomy/term/978">Containers</a> </li> <li> <a href="/tag/desktop">Desktop</a> </li> <li> <a href="/tag/kernel" data-drupal-link-system-path="taxonomy/term/662">Kernel</a> </li> <li> <a href="/tag/mobile">Mobile</a> </li> <li> <a href="/tag/networking">Networking</a> </li> <li> <a href="/tag/privacy">Privacy</a> </li> <li> <a href="/tag/programming">Programming</a> </li> <li> <a href="/tag/security" data-drupal-link-system-path="taxonomy/term/31">Security</a> </li> <li> <a href="/tag/servers">Servers</a> </li> <li class="last"> <a href="/tag/sysadmin" data-drupal-link-system-path="taxonomy/term/21">SysAdmin</a> </li> </ul> </li> <li> <a href="/news" data-drupal-link-system-path="news">News</a> </li> <li class="last"> <a href="/books" data-drupal-link-system-path="books">eBooks</a> </li> </ul> </section> <section class="search-block-form block block-search block-search-form-block clearfix navbar__search col-xs-12 col-sm-4 col-md-4 col-md-offset-0" data-drupal-selector="search-block-form" id="block-linuxjournal-search" role="search"> <h2 class="block-title sr-only">Search</h2> <form action="/search/node" method="get" id="search-block-form" accept-charset="UTF-8"> <div class="form-item js-form-item form-type-search js-form-type-search form-item-keys js-form-item-keys form-no-label form-group"> <label for="edit-keys" class="control-label sr-only">Search</label> <div class="input-group"><input title="Enter the terms you wish to search for." data-drupal-selector="edit-keys" class="form-search form-control" placeholder="Search" type="search" id="edit-keys" name="keys" value="" size="15" maxlength="128" /><span class="input-group-btn"><button type="submit" value="Search" class="button js-form-submit form-submit btn-primary btn icon-only" name=""><span class="sr-only">Search</span><span class="icon glyphicon glyphicon-search" aria-hidden="true"></span></button></span></div> <div id="edit-keys--description" class="description help-block"> Enter the terms you wish to search for. </div> </div> <div class="form-actions form-group js-form-wrapper form-wrapper" data-drupal-selector="edit-actions" id="edit-actions"></div> </form> </section> </div> </div> <div class="navbar-header"> <div class="region region-navigation"> <section id="block-mobilenavigation" class="block block-system block-system-menu-blockmenu-mobile-navbar clearfix col-xs-12 col-md-8 col-md-offset-2 col-lg-8 col-lg-offset-0 navbar__menu navbar__mobilenavigation"> <ul class="menu menu--menu-mobile-navbar nav"> <li class="first"> <a href="/news" data-drupal-link-system-path="news">News</a> </li> <li> <a href="/popular" data-drupal-link-system-path="popular">Popular</a> </li> <li class="last"> <a href="/recent" data-drupal-link-system-path="recent">Recent</a> </li> </ul> </section> </div> </div> </header> </div> </div> <div role="main" class="main-container container js-quickedit-main-content" id="main"> <div class="row"> <section class="col-sm-12"> <div class="highlighted"> <div class="region region-highlighted"> <div data-drupal-messages-fallback class="hidden"></div> </div> </div> <a id="main-content"></a> <div class="region region-content"> <article data-history-node-id="1339928" class="row bs-2col-stacked node node--type-story node--view-mode-full"> <div class="col-sm-12 bs-region bs-region--top"> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden field--items"> <div class="field--item"><div about="/tag/irc" typeof="schema:Thing"> <h2><a href="/tag/irc"> <div property="schema:name" class="field field--name-name field--type-string field--label-hidden field--item">IRC</div> </a></h2> <span property="schema:name" content="IRC" class="hidden"></span> </div> </div> <div class="field--item"><div about="/tag/slack" typeof="schema:Thing"> <h2><a href="/tag/slack"> <div property="schema:name" class="field field--name-name field--type-string field--label-hidden field--item">Slack</div> </a></h2> <span property="schema:name" content="Slack" class="hidden"></span> </div> </div> </div> <div class="field field--name-node-title field--type-ds field--label-hidden field--item"><h1> What Really IRCs Me: Slack </h1> </div> <div class="field field--name-node-author field--type-ds field--label-hidden field--item">by <a title="View user profile." href="/users/kyle-rankin" lang="" about="/users/kyle-rankin" typeof="schema:Person" property="schema:name" datatype="">Kyle Rankin</a></div> <div class="field field--name-node-post-date field--type-ds field--label-hidden field--item">on July 30, 2018</div> </div> <div class="col-sm-9 bs-region bs-region--left"> <div class="shariff" data-services="["twitter","facebook","linkedin","reddit","mail"]" data-theme="white" data-css="complete" data-orientation="horizontal" data-twitter-via="linuxjournal" data-mail-url="mailto:" data-lang="en"> </div> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p><em>Find out how to reconnect to Slack over IRC using a Bitlbee libpurple plugin.</em></p> <p> I'm an IRC kind of guy. I appreciate the simplicity of pure text chat, emoticons instead of emojis, and the vast array of IRC clients and servers to choose from, including the option to host your own. All of my interactive communication happens over IRC either through native IRC channels (like #linuxjournal on Freenode) or using a local instance of Bitlbee to act as an IRC gateway to other chat protocols. Because my IRC client supports connecting to multiple networks at the same time, I've been able to manage all of my personal chat, group chat and work chat from a single window that I can connect to from any of my computers. </p> <p> Before I upgraded to IRC, my very first chat experience was in the late 1990s on a web-based Java chat applet, and although I hold some nostalgia for web-based chat because I met my wife on that network, chatting via a web browser just seems like a slow and painful way to send text across the internet. Also, shortly after we met, the maintainers of that network decided to shut down the whole thing, and since it was a proprietary network with proprietary servers and clients, when they shut it down, all those chat rooms and groups were lost. </p> <p> What's old is new again. Instead of Java, we have JavaScript, and kids these days like to treat their web browsers like Emacs, and so every application has to run as a web app. This leads to the latest trend in chat: Slack. I say the <em>latest</em> trend, because it wasn't very long ago that Hipchat was hip, and before that, even Yammer had a brief day in the sun. In the past, a software project might set up a channel on one of the many public or private IRC servers, but nowadays, everyone seems to want to consolidate their projects under Slack's infrastructure. This means if you joined a company or a software project that started during the past few years, more likely than not, you'll need to use Slack. </p> <p> I'm part of a few Slack networks, and up until recently, I honestly didn't think all that much about Slack, because unlike some other proprietary chat networks, Slack had the sense to offer IRC and XMPP gateways. This meant that you weren't required to use its heavy web app, but instead, you could use whatever client you preferred yet still connect to Slack networks. Sure, my text-based IRC client didn't show animated Giphy images or the 20 party-parrot gifs in a row, but to me, that was a feature. Unfortunately, Slack could no longer justify the engineering effort to backport web chat features to IRC and XMPP, so the company announced it was shutting down its IRC and XMPP gateways. </p> <p> When Slack first announced it was shutting down the IRC gateway, I wasn't sure what I would do. I knew that I wouldn't use the web app, so I figured if an alternative didn't come around, I'd just forget about the Slack networks I was a part of, just like when that old Java chat shut down. Fortunately, the FLOSS community saved the day, and someone wrote a plugin that uses the libpurple library (a kind of Rosetta stone plugin framework for chat used by programs like Pidgin and Bitlbee to allow access to ICQ, MSN, Yahoo and other dead proprietary chat networks). Although using the direct IRC gateway was easier, setting this up on Bitlbee wasn't so bad. So, in this article, I describe how to do exactly that. </p> <span class="h3-replacement"> Why Not Weechat?</span> <p> I know that many console-based chat fans have switched to Weechat as their IRC client, and it has a native Slack plugin. That's great, but I've been using Irssi for something like 15 years, so I'm not about to switch clients just for Slack's sake. Anyway, with the Bitlbee program, you can connect to Slack using your preferred IRC client whether that's Irssi, Xchat or even MIRC (no judgment). </p> <span class="h3-replacement"> Install the Slack libpurple Plugin for Bitlbee</span> <p> Since the Slack Bitlbee plugin uses libpurple, the first step is to make sure you install a Bitlbee package that has libpurple built in. On Debian-based distributions, this means replacing the basic bitlbee package with bitlbee-libpurple if you don't already have it installed. This package should set up a local network service listening on the IRC port automatically. I cover how to use Bitlbee in detail in my past article <a href="https://www.linuxjournal.com/magazine/hack-and-what-really-ircs-me-instant-messaging">"What Really IRCs Me: Instant Messaging"</a>, so I recommend you refer to that article for more details. </p> <p> Once you are connected to Bitlbee, you should be able to issue a <code>help purple</code> command and get a list of existing libpurple plugins that it has installed: </p><pre> <code> 19:23 @greenfly| help purple 19:23 @ root| BitlBee libpurple module supports the ↪following IM protocols: 19:23 @ root| 19:23 @ root| * aim (AIM) 19:23 @ root| * bonjour (Bonjour) 19:23 @ root| * gg (Gadu-Gadu) 19:23 @ root| * novell (GroupWise) 19:23 @ root| * icq (ICQ) 19:23 @ root| * irc (IRC) 19:23 @ root| * msn (MSN) 19:23 @ root| * loubserp-mxit (MXit) 19:23 @ root| * myspace (MySpaceIM) 19:23 @ root| * simple (SIMPLE) 19:23 @ root| * meanwhile (Sametime) 19:23 @ root| * jabber (XMPP) 19:23 @ root| * yahoo (Yahoo) 19:23 @ root| * yahoojp (Yahoo JAPAN) 19:23 @ root| * zephyr (Zephyr) 19:23 @ root| </code> </pre> <p> Note that Slack isn't yet on this list. The next step is to build and install the Slack libpurple plugin on your machine. To do this, make sure you have general build tools installed on your system (for Debian-based systems, the build-essential package takes care of this). Then install the libpurple-devel or libpurple-dev package, depending on your distro. Finally, pull down the latest version of the plugin from GitHub and build it: </p><pre> <code> $ git clone https://github.com/dylex/slack-libpurple.git $ cd slack-libpurple $ sudo make install </code> </pre> <p> (Note: if you don't have system-level access, you can run <code>make install-user</code> instead of <code>sudo make install</code> to install the plugin locally.) </p> <p> Once the install completes, you should have a new library file in /usr/lib/purple-2/libslack.so. Restart Bitlbee, and you should see a new plugin in the list: </p><pre> <code> 19:23 @greenfly| help purple 19:23 @ root| BitlBee libpurple module supports the ↪following IM protocols: 19:23 @ root| 19:23 @ root| * aim (AIM) 19:23 @ root| * bonjour (Bonjour) 19:23 @ root| * gg (Gadu-Gadu) 19:23 @ root| * novell (GroupWise) 19:23 @ root| * icq (ICQ) 19:23 @ root| * irc (IRC) 19:23 @ root| * msn (MSN) 19:23 @ root| * loubserp-mxit (MXit) 19:23 @ root| * myspace (MySpaceIM) 19:23 @ root| * simple (SIMPLE) 19:23 @ root| * meanwhile (Sametime) 19:23 @ root| * slack (Slack) 19:23 @ root| * jabber (XMPP) 19:23 @ root| * yahoo (Yahoo) 19:23 @ root| * yahoojp (Yahoo JAPAN) 19:23 @ root| * zephyr (Zephyr) 19:23 @ root| </code> </pre> <span class="h3-replacement"> Configure Slack in Bitlbee</span> <p> Once you have the Slack module set up, the next step is to configure it like any other Bitlbee network. First, create a new Bitlbee account that corresponds to your Slack account from the Bitlbee console: </p><pre> <code> account add slack username@networkname.slack.com </code> </pre> <p> Next, you'll need to add what Slack calls a Legacy API token, which tells me at some point Slack will deprecate this and leave us out in the cold again. To do this, make sure you are logged in to Slack in your web browser, and then visit <a href="https://api.slack.com/custom-integrations/legacy-tokens">https://api.slack.com/custom-integrations/legacy-tokens</a>. On that page, you will have the ability to generate API tokens for any Slack networks where you are a member. Once you have the API token, go back to your Bitlbee console and set it: </p><pre> <code> account slack set api_token xoxp-jkdfaljieowajfeiajfiawlefje account slack on </code> </pre> <p> If this is the only Slack account you have created, it will label it as "slack", and you can refer to it that way. Otherwise, you'll need to type <code>account list</code> in the Bitlbee console and see how Bitlbee numbered your slack account, and then replace <code>slack</code> in the above commands with the number associated with that account. </p> <p> Unfortunately, unlike with the IRC gateway, this plugin doesn't connect you to any channels in which you are active automatically. Instead, once your Bitlbee client connects, you need to tell Bitlbee about any particular channels you want to join. You can do this with the standard Bitlbee <code>chat add</code> command. So for instance, to add and join the #general channel most Slack networks have, you would type: </p><pre> <code> chat add slack general /join #general </code> </pre> <p> Note that like with the other previous commands, you may need to replace <code>slack</code> with the number associated with your account if you have multiple Slack networks defined. </p> <p> If you want Bitlbee to rejoin a particular room automatically whenever you connect, you can type: </p><pre> <code> channel general set auto_join true </code> </pre> <p> Repeat this for any other channels you want to auto-join. </p> <span class="h3-replacement"> Conclusion</span> <p> Okay, so maybe this article was a little bitter compared to others I've written. I can't help it. It really bothers me when companies use their control over proprietary software, networks or services to remove features upon which people depend. I've also seen so many proprietary chat networks come and go while IRC stays around, that I just wish people would stick with IRC, even if they don't get the animated smiley emoji that turns around in a circle. I'm very thankful for a solid community of developers who are willing to pore through API docs to build new third-party plugins when necessary. </p></div> <div class="field field--name-dynamic-token-fieldnode-author field--type-ds field--label-hidden field--item"><div> <img loading="lazy" src="/sites/default/files/pictures/picture-1002206.jpg" width="85" height="84" typeof="foaf:Image" class="img-responsive" /> </div> <p> Kyle Rankin is a Tech Editor and columnist at <em>Linux Journal</em> and the Chief Security Officer at Purism. He is the author of <em>Linux Hardening in Hostile Networks</em>, <em>DevOps Troubleshooting</em>, <em>The Official Ubuntu Server Book</em>, <em>Knoppix Hacks</em>, <em>Knoppix Pocket Reference</em>, <em>Linux Multimedia Hacks</em> and <em>Ubuntu Hacks</em>, and also a contributor to a number of other O'Reilly books. Rankin speaks frequently on security and open-source software including at BsidesLV, O'Reilly Security Conference, OSCON, SCALE, CactusCon, Linux World Expo and Penguicon. You can follow him at @kylerankin. </p> </div> <section class="section--disqus"> <a id="comments-link" class="btn btn-default" href="https://www.linuxjournal.com/content/what-really-ircs-me-slack#disqus_thread">Load Disqus comments</a> <div id="disqus_thread"></div> <noscript>Our discussions are <a href="https://disqus.com/?ref_noscript" rel="nofollow">powered by Disqus</a>, which require JavaScript.</noscript> </section> </div> <div class="col-sm-3 bs-region bs-region--right"> <div class="field field--name-dynamic-block-fieldnode-sidebar-image field--type-ds field--label-hidden field--item"><div class="views-element-container form-group"><div class="view view-sidebar-image view-id-sidebar_image view-display-id-block_1 js-view-dom-id-68881561ae8e2d0e813798ea4a1ac868883e1372e4169e0ea13d71df5f991cc2"> </div> </div> </div> <div class="field field--name-dynamic-block-fieldnode-recent-content field--type-ds field--label-hidden field--item"><div class="views-element-container form-group"><div class="view view-related-content view-id-related_content view-display-id-block_2 js-view-dom-id-0c0e5d53774edc34b52072b6286628d33ae523f8457da895ac5a0cb912ffe36b"> <div class="view-header"> <h2 class="block-title">Recent Articles</h2> </div> <div class="view-content"> <div class="views-row"><div class="views-field views-field-field-node-image"><div class="field-content"> <a href="/content/streamline-your-logs-exploring-rsyslog-effective-system-log-management-ubuntu" hreflang="en"><img loading="lazy" src="/sites/default/files/styles/75x75_square/public/nodeimage/story/streamline-your-logs-exploring-rsyslog-for-effective-system-log-management-on-ubuntu.jpg?itok=KOKPK6kO" width="75" height="75" alt="Streamline Your Logs: Exploring Rsyslog for Effective System Log Management on Ubuntu" typeof="foaf:Image" class="img-responsive" /> </a> </div></div><div class="views-field views-field-title"><span class="field-content"><a href="/content/streamline-your-logs-exploring-rsyslog-effective-system-log-management-ubuntu" hreflang="en">Streamline Your Logs: Exploring Rsyslog for Effective System Log Management on Ubuntu</a></span></div><div class="views-field views-field-uid"><span class="field-content"><a href="/users/george-whittaker" hreflang="en">George Whittaker</a></span></div></div> <div class="views-row"><div class="views-field views-field-field-node-image"><div class="field-content"> <a href="/content/linux-networking-protocols-understanding-tcpip-udp-and-icmp" hreflang="en"><img loading="lazy" src="/sites/default/files/styles/75x75_square/public/nodeimage/story/linux-networking-protocols-understanding-tcpip-udp-and-icmp.jpg?itok=fQ2nxIqH" width="75" height="75" alt="Linux Networking Protocols: Understanding TCP/IP, UDP, and ICMP" typeof="foaf:Image" class="img-responsive" /> </a> </div></div><div class="views-field views-field-title"><span class="field-content"><a href="/content/linux-networking-protocols-understanding-tcpip-udp-and-icmp" hreflang="en">Linux Networking Protocols: Understanding TCP/IP, UDP, and ICMP</a></span></div><div class="views-field views-field-uid"><span class="field-content"><a href="/users/george-whittaker" hreflang="en">George Whittaker</a></span></div></div> <div class="views-row"><div class="views-field views-field-field-node-image"><div class="field-content"> <a href="/content/leveraging-tmux-and-screen-advanced-session-management" hreflang="en"><img loading="lazy" src="/sites/default/files/styles/75x75_square/public/nodeimage/story/leveraging-tmux-and-screen-for-advanced-session-management.jpg?itok=AcOn-co4" width="75" height="75" alt="Leveraging Tmux and Screen for Advanced Session Management" typeof="foaf:Image" class="img-responsive" /> </a> </div></div><div class="views-field views-field-title"><span class="field-content"><a href="/content/leveraging-tmux-and-screen-advanced-session-management" hreflang="en">Leveraging Tmux and Screen for Advanced Session Management</a></span></div><div class="views-field views-field-uid"><span class="field-content"><a href="/users/george-whittaker" hreflang="en">George Whittaker</a></span></div></div> <div class="views-row"><div class="views-field views-field-field-node-image"><div class="field-content"> <a href="/content/enhancing-system-security-and-efficiency-through-user-and-group-management" hreflang="en"><img loading="lazy" src="/sites/default/files/styles/75x75_square/public/nodeimage/story/enhancing-system-security-and-efficiency-through-user-and-group-management.jpg?itok=wZFrU9iN" width="75" height="75" alt="Enhancing System Security and Efficiency through User and Group Management" typeof="foaf:Image" class="img-responsive" /> </a> </div></div><div class="views-field views-field-title"><span class="field-content"><a href="/content/enhancing-system-security-and-efficiency-through-user-and-group-management" hreflang="en">Enhancing System Security and Efficiency through User and Group Management</a></span></div><div class="views-field views-field-uid"><span class="field-content"><a href="/users/george-whittaker" hreflang="en">George Whittaker</a></span></div></div> <div class="views-row"><div class="views-field views-field-field-node-image"><div class="field-content"> <a href="/content/debian-package-dependency-management-handling-dependencies" hreflang="en"><img loading="lazy" src="/sites/default/files/styles/75x75_square/public/nodeimage/story/debian-package-dependency-management-handling-dependencies.jpg?itok=uSuvvAlA" width="75" height="75" alt="Debian Package Dependency Management: Handling Dependencies" typeof="foaf:Image" class="img-responsive" /> </a> </div></div><div class="views-field views-field-title"><span class="field-content"><a href="/content/debian-package-dependency-management-handling-dependencies" hreflang="en">Debian Package Dependency Management: Handling Dependencies</a></span></div><div class="views-field views-field-uid"><span class="field-content"><a href="/users/george-whittaker" hreflang="en">George Whittaker</a></span></div></div> <div class="views-row"><div class="views-field views-field-field-node-image"><div class="field-content"> <a href="/content/simplifying-user-accounts-and-permissions-management-linux" hreflang="en"><img loading="lazy" src="/sites/default/files/styles/75x75_square/public/nodeimage/story/simplifying-user-accounts-and-permissions-management-in-linux.jpg?itok=ka6wpila" width="75" height="75" alt="Simplifying User Accounts and Permissions Management in Linux" typeof="foaf:Image" class="img-responsive" /> </a> </div></div><div class="views-field views-field-title"><span class="field-content"><a href="/content/simplifying-user-accounts-and-permissions-management-linux" hreflang="en">Simplifying User Accounts and Permissions Management in Linux</a></span></div><div class="views-field views-field-uid"><span class="field-content"><a href="/users/george-whittaker" hreflang="en">George Whittaker</a></span></div></div> </div> </div> </div> </div> <div class="field field--name-dynamic-block-fieldnode-sponsors field--type-ds field--label-hidden field--item"><div class="views-element-container form-group"><div class="view view-latest-sponsor-block view-id-latest_sponsor_block view-display-id-block_1 js-view-dom-id-4e20809159bb61db6b964985615a9babe905d0423a188153441935821882c9be"> <div class="view-header"> </div> <div class="view-content"> <div class="views-row"> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"> </div> </div> </div> </div> </div> </div> </div> </article> </div> </section> </div> </div> <footer class="footer container" role="contentinfo"> <div class="region region-footer"> <section class="views-element-container block block-views block-views-blocknewsletter-promo-block-block-1 clearfix" id="block-views-block-newsletter-promo-block-block-1"> <div class="form-group"><div class="view view-newsletter-promo-block view-id-newsletter_promo_block view-display-id-block_1 js-view-dom-id-3dfbc67c695ad1bb38014f0d1ed67dfb8d9d06f2c023d614ad6745d0ea4a194f"> <div class="view-content"> <div class="views-row"> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><div class="newsletter-bottom"> <div class="col-md-9 col-sm-12 signup-form"> <!--<h3>Linux Journal Week in Review</h3> <p>Sign up to get all the good stuff delivered to your inbox every week.</p> <form id="subForm" class="js-cm-form" action="https://www.createsend.com/t/subscribeerror?description=" method="post" data-id="A61C50BEC994754B1D79C5819EC1255CDBC34DDF3E170B13E2BAC2D68C42BF424F853383C84F5BAE38EAB4CFA5C73907CAC074FF8192503AF80F3699F7FE5CE1"> <div class="flexform">--> <!--<label for="fieldEmail">Email</label> <br />--> <!--<input id="fieldEmail" name="cm-gjjtdh-gjjtdh" type="email" class="js-cm-email-input" placeholder="Enter your email. Get the newsletter." required /> <button class="js-cm-submit-button" type="submit">Sign Up</button> </div> <div> <input id="cm-privacy-consent" name="cm-privacy-consent" required type="checkbox" /> <label for="cm-privacy-consent">I give my consent to be emailed</label> <input id="cm-privacy-consent-hidden" name="cm-privacy-consent-hidden" type="hidden" value="true" /> </div> </form> <script type="text/javascript" src="https://js.createsend1.com/javascript/copypastesubscribeformlogic.js"></script> </div>--> <!--<div class="col-md-3 col-sm-12 subs-callout"> <img src="/sites/default/files/styles/large/public/2019-01/LJ294-Jan2019-Cover_0.jpg" width="100px" /> <h3>The Value of Open Source Journalism</h3> <p> Subscribe and support our coverage for technology's biggest thinkers – with up to 52% savings. </p> <strong><a href="https://www.linuxjournal.com/subscribe">Subscribe <i class="fa fa-angle-double-right" aria-hidden="true"></i></a> </strong> </div>--> </div> </div> </div> </div> </div> </div> </section> </div> <div class="footer-blocks col-sm-12"> <div class="col-md-6 col-sm-12 footer-left"> <div class="region region-footer-left"> <section id="block-connectwithusfooter" class="block block-block-content block-block-content5e722bd4-5e08-454b-8507-956089bfa661 clearfix"> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><div class="footer-heading">Connect With Us <span class="social-media sm-a-no-underline"><a href="https://youtube.com/linuxjournalonline" alt="Linux Journal on YouTube" aria-label="YouTube"><i class="fa fa-youtube fa-2x"></i></a><a href="https://www.facebook.com/linuxjournal/" alt="Linux Journal on Facebook" aria-label="Facebook"><i class="fa fa-facebook-f fa-2x"></i><a href="https://twitter.com/linuxjournal" alt="Linux Journal on Twitter" aria-label="Twitter"><i class="fa fa-twitter fa-2x"></i></a></span></div> <p>Linux Journal, representing 25+ years of publication, is the original magazine of the global Open Source community.</p></div> </section> <section id="block-linuxjournal-block-9" class="block block-block-content block-block-content8669793b-e217-4426-a79e-eb3c21ede127 clearfix"> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><div id="copyright">© 2025 Slashdot Media, LLC. All rights reserved.</div> </div> </section> <section id="block-privacyterms" class="block block-block-content block-block-contenta203b8bd-80ef-4982-bf6e-784dd7b44120 clearfix"> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><ul class="menu menu--footer-submenu nav" id="terms-nav"> <li><a href="https://slashdotmedia.com/privacy-statement/" rel="nofollow" target="_blank">PRIVACY POLICY</a></li> <li><a href="https://slashdotmedia.com/terms-of-use/" rel="nofollow" target="_blank">TERMS OF SERVICE</a></li> <li><a href="/sponsors">ADVERTISE</a></li> </ul></div> </section> </div> </div> <div class="col-md-4 col-sm-8 footer-middle"> <div class="region region-footer-middle"> <nav role="navigation" aria-labelledby="block-footermenucolumn2-menu" id="block-footermenucolumn2"> <h2 class="visually-hidden" id="block-footermenucolumn2-menu">Footer Menu Column 2</h2> <ul class="menu menu--footer-menu-column-2 nav"> <li class="first"> <a href="/content/masthead" data-drupal-link-system-path="node/1007727">Masthead</a> </li> <li> <a href="/author" data-drupal-link-system-path="node/1009249">Authors</a> </li> <li class="last"> <a href="/form/contact" data-drupal-link-system-path="webform/contact">Contact Us</a> </li> </ul> </nav> <nav role="navigation" aria-labelledby="block-footermenucolumn3-menu" id="block-footermenucolumn3"> <h2 class="visually-hidden" id="block-footermenucolumn3-menu">Footer Menu Column 3</h2> <ul class="menu menu--footer-menu-column-3 nav"> <li class="first"> <a href="/rss_feeds" data-drupal-link-system-path="node/1000457">RSS Feeds</a> </li> <li class="last"> <a href="/aboutus" data-drupal-link-system-path="node/1000267">About Us</a> </li> </ul> </nav> </div> </div> </div> </footer> </div> </div> <script type="application/json" data-drupal-selector="drupal-settings-json">{"path":{"baseUrl":"\/","scriptPath":null,"pathPrefix":"","currentPath":"node\/1339928","currentPathIsAdmin":false,"isFront":false,"currentLanguage":"en"},"pluralDelimiter":"\u0003","suppressDeprecationErrors":true,"bootstrap":{"forms_has_error_value_toggle":1,"popover_enabled":1,"popover_animation":1,"popover_auto_close":1,"popover_container":"body","popover_content":"","popover_delay":"0","popover_html":0,"popover_placement":"right","popover_selector":"","popover_title":"","popover_trigger":"click"},"linuxjournal":{"disqus":{"origin":"https:\/\/www.linuxjournal.com","prettyUrl":"\/content\/what-really-ircs-me-slack","fullUrl":"https:\/\/www.linuxjournal.com\/content\/what-really-ircs-me-slack","embedUrl":"https:\/\/linuxjournal.disqus.com\/embed.js","shortname":"linuxjournal"}},"statistics":{"data":{"nid":"1339928"},"url":"\/core\/modules\/statistics\/statistics.php"},"ajaxTrustedUrl":{"\/search\/node":true},"user":{"uid":0,"permissionsHash":"a7b3a803411eb9cbd5d7d374ffb326721ee8274ab5a665df8f38311e3aad858c"}}</script> <script src="/core/assets/vendor/jquery/jquery.min.js?v=3.6.3"></script> <script src="/core/assets/vendor/underscore/underscore-min.js?v=1.13.6"></script> <script src="/core/misc/polyfills/element.matches.js?v=9.5.9"></script> <script src="/core/misc/polyfills/object.assign.js?v=9.5.9"></script> <script src="/core/assets/vendor/once/once.min.js?v=1.0.1"></script> <script src="/core/assets/vendor/jquery-once/jquery.once.min.js?v=9.5.9"></script> <script src="/core/misc/drupalSettingsLoader.js?v=9.5.9"></script> <script src="/core/misc/drupal.js?v=9.5.9"></script> <script src="/core/misc/drupal.init.js?v=9.5.9"></script> <script src="/themes/contrib/bootstrap/js/drupal.bootstrap.js?snzigw"></script> <script src="/themes/contrib/bootstrap/js/attributes.js?snzigw"></script> <script src="/themes/contrib/bootstrap/js/theme.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/affix.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/alert.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/button.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/carousel.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/collapse.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/dropdown.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/modal.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/tooltip.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/popover.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/scrollspy.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/tab.js?snzigw"></script> <script src="/themes/linuxjournal/bootstrap/assets/javascripts/bootstrap/transition.js?snzigw"></script> <script src="/themes/linuxjournal/js/lj-consentmanager.js?snzigw"></script> <script src="/modules/contrib/webform/js/webform.behaviors.js?v=9.5.9"></script> <script src="/core/misc/jquery.once.bc.js?v=9.5.9"></script> <script src="/core/misc/states.js?v=9.5.9"></script> <script src="/themes/contrib/bootstrap/js/misc/states.js?snzigw"></script> <script src="/modules/contrib/webform/js/webform.states.js?v=9.5.9"></script> <script src="/modules/contrib/webform/modules/webform_bootstrap/js/webform_bootstrap.states.js?v=9.5.9"></script> <script src="/themes/contrib/bootstrap/js/popover.js?snzigw"></script> <script src="/core/modules/statistics/statistics.js?v=9.5.9"></script> <script src="/themes/linuxjournal/js/lj-disqus.js?snzigw"></script> <script src="/libraries/shariff/shariff.complete.js?v=9.5.9"></script> <!-- START EMBED --> <noscript><img src="https://api.b2c.com/api/noscript-448i7exgpyqpr9c144q.gif"></noscript> <!-- END EMBED --> <!-- Matomo --> <script type="text/javascript"> var _paq = _paq || []; function initPiwik() { _paq.push(['trackPageView']); _paq.push(['enableLinkTracking']); (function() { var u="https://analytics.linuxjournal.com/"; _paq.push(['setTrackerUrl', u+'piwik.php']); _paq.push(['setSiteId', '50']); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s); })(); } </script> <noscript><p><img src="https://analytics.linuxjournal.com/piwik.php?idsite=50&rec=1" style="border:0;" alt="" /></p></noscript> <!-- End Matomo Code --> <div class="modal-custom overlay-custom" id="ccpa-modal" style="margin-left: 0; display: none; max-width: 100%; width: 100%"> <div id="modal-content" class="modal-content"> <div class="modal-header" id="ccpa-modal-content-destination"></div> <span class="close" id="modal-close">×</span> </div> </div> </body> </html>