artlung.

←January 2018March 2018→

February, 2018: 29 posts.

John Perry Barlow, Rest in Peace 2018 Feb 07

I went to Jason Calacanis’ conference Digital Coast 2000 way back when. I didn’t write about it, but it was inspiring. I found Calacanis inspiring, he’s a raconteur and a troublemaker and I have enjoyed his podcasts over the years. The other standouts from that conference were Mark Cuban who I quoted long ago The minute you think you’re smart — you’re toast. I wish I’d kept notes from hearing Barlow speak.

Here’s the description of that conference I got out of the web archive:

Exploring the Digital Transformation of Entertainment and Southern California’s Booming Internet Economy

September 12-14, 2000 at the Directors Guild of America, Los Angeles

Digital Coast 2000 is the second annual gathering of the leading executives, artists and technologists building Southern California’s burgeoning digital industries. The three-day event takes place in association with The Directors Guild of America and NATPE with the support of Variety.

We’re thrilled to announce a number of newly-added guest speakers, including: Shaquille O’Neal, NBA reigning MVP & World Champion, and Co-founder & Principal, Dunk.net; Award-winning directors Wayne Wang (Joy Luck Club, Smoke, Blue in the Face), Penelope Spheeris (Wayne’s World, Decline of Western Civilization); and Alex Singer (director of more than 250 TV and 5 motion pictures including Stanley Kubrick‘s first feature, Day of the Fight); Stan Lee Media Founder, Chairman and Chief Creative Officer Stan Lee; Centropolis Partner Dean Devlin; Digital Media Campus Chairman and CEO Leonard Armato; Acclaimed cinematographer Theo Van de Sande; Project Voyager CEO and co-founder Joe Firmage; RIAA CEO Hilary Rosen; and David O. Carson, General Counsel for the U.S. Copyright Office.

The three-day agenda features keynote and fireside chats with e-business leaders including Broadcast.com CEO Mark Cuban and Idealab Chairman Bill Gross. Panels on the e-Business Track include an e-services CEOs roundtable with Jeff Dachis of Razorfish, Bert Ellis of IXL, Robert Bernard of MarchFirst, Bob Gett of Viant, and Scott Mednick of Xceed; a “Digital Coast Enterprise Success Stories” panel examining how mature companies are re-engineering through Internet technology and new, networked operational models; “Internet Book Publishing and Online Literature” with leading executives and e-published authors, and a roundtable of top Digital Coast VC’s on the state of venture capital in Southern California.

Topics on the Digital Coast 2000 Convergence Track include “The e-Biznification of Hollywood” in which top executives from major and independent motion picture studios examine the Internet’s impact on the film industry;“The Animation Renaissance” featuring exclusive premiere screenings from top online animation producers; an Interactive and Enhanced Television panel showcasing live demos from award-winning enhanced TV content creators and the American Film Institute; “Talent Rights: Artists, Agencies and the Risks and Rewards of Online Opportunities” on the new Internet agreements with leaders of the DGA, SAG, and WGA; and panels such as “The Future of Intellectual Property” and “Music, Money and The P2P Revolution” including Ian Clarke of Freenet, Gene Kan of Infrasearch, Bill Bales of Applesoup, Jim Griffin of Evolab; and EFF co-founder John Perry Barlow.

Online entertainment creators at Digital Coast 2000 include Bruce Branit and Jeremy Hunt of “405 The Movie”and Joseph Levy of “George Lucas In Love”; plus special international guest Gordan Paunovic, co-founder of RadioB92 Belgrade.

We’re also very proud to announce the first annual Digital Coast Awards for excellence in digital entertainment — we’ll be honoring some of the hottest online entertainment projects from the past year at a special ceremony on September 14, from 4:30 to 6:30 p.m.

What I remember of Barlow was that he really helped me understand what internet sharing was about. Napster and intellectual property were deeply in the news, and Barlow contextualized internet sharing as part of music history. The Grateful Dead famously allowed fans to record and share their music. It helped me put internet freedom and “intellectual property” on my map of free public goods — libraries and shared knowledge in the form of science. He was inspirational.

Barlow was in the zeitgeist of the time back then. Here’s something from Courtney Pulitzer’s CyberScene, a quote from Barlow from 1999 about his own mother dying:

A vertible institution himself, the great woman (and institution) behind the great man — John Perry Barlow — is Miriam Jenkins Barlow Bailey. John’s mother died a few weeks ago and he sent a moving tribute about her to friends, and granted me permission to reprint it with her picture.

John wrote: “My mother was immense, *much* larger than life. No one who met her came away untouched – or unscathed, as the case may have been. She has kept an electric tension on a line that ran through the center of my life all its course. Now, all at once, that line’s gone slack. The world is suddenly a far less interesting place. Some years ago, shortly after his own mother died, John Kennedy, Jr. mused to me, ‘I don’t think anyone really becomes an adult until both of his parents are dead.’ Now I’m starting to understand what he meant. …”

How sadly ironic that John quotes his friend JFK, Jr., who he (in addition to the rest of the world) has had to say goodbye to also. I saw Mr. Barlow on television talking about his friendship with JFK, Jr. this past week, and can only think of how the world does seems a far less interesting place when one loses someone dear. Death is a great and final tragedy, but as John and as JFK, Jr. both indicate, it’s a release, a dawning and forces us to grow up a little more, straighten our back, lift our chin and go boldly forward as an “adult.”

God Bless Miriam Jenkins Barlow Bailey, John F. Kennedy Jr., Carolyn Bessette Kennedy and Lauren Bessette. May they all go forth in peace and may we all breathe a bit deeper today in appreciation of our gift of Life.

From the EFF: John Perry Barlow, Internet Pioneer, 1947-2018

Random Notes on #lightningnow Tour / Trailhead / Salesforce 2018 Feb 09

On January 29th and 30th I attended the Lighting Tour of Salesforce.com that was held here in San Diego. I had a lot of fun, and got a great sense that my skills in web development may have a great deal of carryover into working with and developing for Salesforce.

Cutest stickers at @salesforce #lightningnow seminar here in San Diego. Added to my iPad though I took my notes on paper today. Day 2 of #lightningnow learning about Kanban view inside @Salesforce + bonus t-shirt! Remain impressed by quality of Trailhead exercises for a novice like me. I also like that it’s kind of Shazam!/Mage/Captain Marvel.

Here’s the code editor that is part and parcel of developing for Salesforce.

In web development one has to be cognizant of issues related to caching when making frequent updates. Here’s the setting you’d look for to make sure you’re seeing freshly edited content.

I was very impressed with the API versioning that’s a part of Salesforce. You can target different versions of Apex and in this way you can migrate to newer API versions as you need to in a manner that’s safe. Salesforce can keep innovating, and your apps won’t break. That’s smart.

I was also very interested to see the differences in code from “old style” and their “new style.” Of course I had no concept of the older style but I can see that they’ve taken some time to encapsulate very robust and common functionality in ways that are quicker to develop for.

Installing a new Project screen. I’m not sure what made me capture this one actually. Possibly I just thought to myself: this is some pretty professional and polished stuff. Which is the impression I got generally.

It’s a few weeks later and I’m having fun going through the tutorials and exercises on Trailhead.

Here’s my profile on Trailhead: Joe Crawford

Backup your Soundcloud files to Archive.org 2018 Feb 13

Well here’s something cool! My pal Dennis Wilen backed up his Soundcloud hosted files to Archive.orgWe backed up my SoundCloud to Archive.org and you can too.

There’s a shell script by Tom Higgins that facilitates it.

I don’t understand the excess rules about ferrets or the deficit of rules about guns. 2018 Feb 15

We (the government) regulate hairdressers and car exhaust and doctors and lawyers and how you add a new room to your house and we license you to drive a car and regulate boats and regulate your speed on the interstate and how you educate your children and test whether your toys are safe and whether your lettuce is clean and we regulate what the word “organic” means on a food package and we regulate how people houses are sold so it’s fair and we monitor air quality and we regulate how much you get paid on unemployment and we regulate how and who can vote and we have rules on lead in paint and we regulate if you can own a ferret in some places. Most of us see these as good things because a hairdresser not meeting standards can hurt you and cars with too much emissions cause smoke and untrained doctors and lawyers are a terrible idea and you need to learn to drive a car properly if you’re going to drive and if you’re going to teach your kids yourself you aught to do it right and if the lettuce isn’t clean you can get really sick and if something is “organic” it should actually mean something and the real estate business has a really shady history of treating people different based on race so we need to fix that and we should keep track of air quality because again, health and yes we should make sure people who vote have the right to vote (although more of us really should vote because we all have a stake in this world) and lead in paint has this really terrible history of hurting people bad and while I don’t understand why some places don’t allow ferrets, even worse I have no idea why my idea of monitoring and regulating firearms better — as in, in such a way that we maybe get less people killed every year — makes me Un-American.

(Originally posted to Medium)

WordFence is vital for self-hosted WordPress instances. 2018 Feb 19

I’ve been hosting WordPress websites for a long time. This blog I migrated to WordPress in 2004. I had experience with it running San Diego Blog which started on B2 and I converted to WordPress in Summer 2004. So I’ve been hosting WordPress a long time. There’s a reason the software is popular. It’s free, flexible, straightforward to customize, theme, improve, update.

This ease-of-use has brought ubiquity. So much so I attended Creative Mornings San Diego the other morning and one of the sponsors was WordPress. The short description of WordPress included the tagline “powering 25% of websites.”

Ubiquity has made WordPress an extraordinarily attack surface area for hackers. (Like Windows has been for a long time! Yay?!) I’ve seen hacks against user accounts, against the upload feature, I’ve seen worms, and DOS attacks and everything in-between. An absolutely vital tool for me has been WordFence. They’ve done a great job on the free version of the tool. I feel like the paid version is a bit too pricy for my own usage, but WordFence version 7 has been a great update already. This blog has had some targeted SQL injection attacks as well as some suspicious user creation behavior directed at it that WordFence alerted me to and thwarted successfully.

I run several other websites and having WordFence do this kind of work and keeping me up to date keeps my mind at ease.

17 Years And Counting 2018 Feb 19

In 2001 I started blogging via blogger.com. It allowed me to augment my personal site using blog with an external service via FTP and experiment with regularly writing. On this anniversary I have commemorated this before: 2002, 2003, 2004, 2007, 2011, 2014, and 2015.

In 2003 I wrote:

I am at a loss, but it’s not for public condemnation or praise. I would like this blog to be a conduit for finding work and for sharing my thoughts on the technical things which jazz up my life. I also want it, now I realize, as a means to share my experience.

And these many years later that’s pretty much what it’s for. Granted, much of what I do now is cross-post my Instagram posts but still, I’m using this more as my own showcase, for my imperfect self to play with technology.

Just a few months after I started the site here’s what the site looked like when you landed on it, note the blog in the right column:

I’m still learning to blog, and still blogging, and still experimenting.

Most Steps. 2018 Feb 19

I did an export using Pedometer++ and here’s a graph of my steps for the last several years.

That corresponds to a 4 and a half mile walk I took. I’m not sure why there’s an off by one error or why there are so many zero-step days. (Was I bedridden?) But I love the trends, such as they are, regardless.

Previously.

March Modok Madness is coming! 2018 Feb 20

I never posted about the fact that I did a second MODOK in 2012. I mentioned the first one I did here, but not the second.

What? You’ve never heard of March MODOK Madness?

You’ve never heard of MODOK? Read about him!

Blog Post Visualization + Code 2018 Feb 21

I’ve been doing maintenance galore on this site. I have a hand-written theme and I’ve been doing things like returning the footer to a good shape and sweating the responsive details of it.

I first wrote that code in 2010 but I’ve adapted it to be a bit better and now am using CSS Grid to allow those columns to display a bit better on different screen sizes and form factors.

The header has a similar but not quite the same treatment on archive pages to allow navigating from month to month and year to year quickly.

Like I said, I first wrote the code for the years and months visualization back in 2010.

The PHP code has not changed a great deal from 2010:

	<div id="sidebar" class="sidebar-archive">

	<?php

	/* show archive information */
	$args = array(
		'type'            => 'monthly',
		'format'          => 'custom', 
		'show_post_count' => true,
		'echo'            => 0 ); 
	$resulthtml = wp_get_archives($args); 
	$archives = array_map('trim', explode("\n", $resulthtml));
	$archiveMonths = array();
	foreach($archives as $item) {
		if (trim($item)!='') {
			$archiveMonths[] = trim($item);
		}
	}
	$archiveMonths = array_reverse($archiveMonths);

	$archiveLinks = array();
	$yearCount = array();

	foreach ($archiveMonths as $link) {
		// link looks like:
		// <a href='http://artlung.com/blog/2001/02/' title='February 2001'>February 2001</a> (9)
		// we want it to look like:
		// <a href='http://artlung.com/blog/2001/02/' title='February 2001' style='background-position: -9px'>February</a>
		// and we need the year;
		// and we need the count;
		$cssInitial = 400;
		$temp = explode('</a>', $link);
		// [0] <a href='http://artlung.com/blog/2001/02/' title='February 2001'>February 2001
		// [1]  (9)
		$count = (int)str_replace(array(' (', '('),'',$temp[1]);
		// 0 ... -400
		// 5 ... -395
		// 10 .. -390
		// 20 .. -380
		$cssCount = ($count) - $cssIniital;
		$year = (int)substr($temp[0],-4);
		$yearCount[$year] += $count;

// 		$newLink = str_replace('\'>', ", {$count} posts.' style='background-position: {$cssCount}px 0;'>", substr($temp[0], 0, -5)) . "</a>";
		$newLink = str_replace('\'>', "' style='background-position: {$cssCount}px 0;'>", substr($temp[0], 0, -5)) . "</a>";

		$archiveLinks[$year][] = $newLink;//str_replace($just_text, $month, $link);
	}
	foreach ($archiveLinks as $k => $v) {
		print '<div class="archiveYear">';
		print "<h4><a href=\"/blog/{$k}/\" title=\"{$yearCount[$k]} posts in the year {$k}.\">{$k}</a></h4>";
		print '<ul><li>' . implode("</li>\n<li>", $v) . '</li></ul>';
		print '</div>';
	}

	?>
	
	
	</div>

And the CSS looks like this:

.sidebar-archive {
  background-color: #000;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.sidebar-archive .archiveYear {
  width: 100%;
}

@media screen and (min-width: 500px) {
  .sidebar-archive {
    grid-template-columns: repeat(5, 1fr);
  }
}
@media screen and (min-width: 600px) {
  .sidebar-archive {
    grid-template-columns: repeat(6, 1fr);
  }
}
@media screen and (min-width: 700px) {
  .sidebar-archive {
    grid-template-columns: repeat(7, 1fr);
  }
}
@media screen and (min-width: 800px) {
  .sidebar-archive {
    grid-template-columns: repeat(8, 1fr);
  }
}
@media screen and (min-width: 900px) {
  .sidebar-archive {
    grid-template-columns: repeat(9, 1fr);
  }
}
@media screen and (min-width: 1000px) {
  .sidebar-archive {
    grid-template-columns: repeat(10, 1fr);
  }
}
@media screen and (min-width: 1100px) {
  .sidebar-archive {
    grid-template-columns: repeat(11, 1fr);
  }
}
@media screen and (min-width: 1200px) {
  .sidebar-archive {
    grid-template-columns: repeat(12, 1fr);
  }
}
.archiveYear {
  width: 100px;
  background-color: #000;
  padding: 0;
  margin: 0;
  display: inline-block;
  height: 250px;
}
.archiveYear h4 {
  background-color: #000;
  padding: 15px;
  margin: 0;
  color: #fff;
  text-align: left;
  font-size: small;
  font-weight: normal;
  text-decoration: none;
}
.archiveYear h4 a {
  padding: 15px;
  margin: 0;
  text-align: left;
  font-size: small;
  font-weight: normal;
  text-decoration: none;
  color: #fff;
}
.archiveYear h4 a:visited {
  color: #fff;
}
.archiveYear h4 a:hover {
  color: #fff;
}
.archiveYear h4 a:link {
  color: #fff;
}
.archiveYear h4 a:active {
  color: #fff;
}
.archiveYear ul {
  padding: 0;
  margin: 0;
  list-style-type: none;
  font-size: small;
  height: 250px;
}
.archiveYear ul li {
  padding: 0 15px;
  text-align: left;
}
.archiveYear ul li a {
  text-decoration: none;
  color: #fff;
  background-color: blue;
  display: block;
  padding: 2px;
  cursor: pointer;
  background-image: url(images/black-500x30.gif);
  background-repeat: no-repeat;
}

The source code for all of this is available on GitHub. It also includes the SASS source code for the stylesheets. There are additional notes as well.

If anyone has any questions or comments, please give me a shout!

Suspicious Activity: “An admin user with the username backup was created outside of WordPress” 2018 Feb 22

On 14 February 2018, WordFence alerted me to highly suspicious behavior. This is the format of the email I received from WordFence version 4.9.3:

This email was sent from your website “[REDACTED BLOG NAME]” by the Wordfence plugin.

Wordfence found the following new issues on “[REDACTED BLOG NAME]”.

Alert generated at Wednesday 14th of February 2018 at 12:07:50 PM

Critical Problems:

* An admin user with the username backup was created outside of WordPress.

NOTE: You are using the free version of Wordfence. Upgrade today:

Receive real-time Firewall and Scan engine rule updates for protection as threats emerge
Other advanced features like IP reputation monitoring, country blocking, an advanced comment spam filter and cell phone sign-in give you the best protection available
Remote, frequent and scheduled scans
Access to Premium Support
Discounts of up to 90% for multiyear and multi-license purchases
Click here to upgrade to Wordfence Premium:
https://www.wordfence.com/zz2/wordfence-signup/

This is suspicious on its own, but I wondered if it might be benign. Or at worst, maybe was a plugin gone bonkers. Or maybe my web host was doing something wonky. But strangely, when looking at the accounts in the database I noticed there was no nickname or email address associated with the account. WordPress requires both to create an account if you go through the normal way.

This email was sent from your website “[REDACTED BLOG NAME]” by the Wordfence plugin at Wednesday 14th of February 2018 at 08:28:38 AM

The Wordfence administrative URL for this site is: http://example.org/wp-admin/admin.php?page=Wordfence

A user with username “backup” who has administrator access signed in to your WordPress site.

User IP: 35.183.24.90
User hostname: ec2-35-183-24-90.ca-central-1.compute.amazonaws.com
User location: Montreal, Canada

…then WordFence alerted me this user logged in from an EC2 instance.

Then I got 5 more log-ins in the space of about 10 minutes to other sites I maintain. From the same computer. In my mind, this elevated “suspicious” to “probably malicious.” In that moment I was very glad for my MySQL backup processes that would allow me to go back a few days in time before this nonsense.

The behavior was so swift I wonder about whether it was automated, but logging in with saved credentials is not a terrible slow operation even for a person.

The lack of email address on the accounts implies, to me a concrete plan. No email address means they would have no way to reset their password but also no way for me to track them by email.

I knew I wanted to remove access for this user. So for each I needed to

    1. Change their password
    2. Log them out
    3. Add an email address I control for each account
    4. Change the SALT for the password encryption for each site.

So I did 1, 2, and 3. I used the standard WordPress user administration panel to change each password and log each out. I also added an email address using the gmail “+whatever” format:

Append a plus (“+”) sign and any combination of words or numbers after your email address. For example, if your name was hikingfan@gmail.com, you could send mail to hikingfan+friends@gmail.com or hikingfan+mailinglists@gmail.com.

I kept a list of the sites I was modifying as I went. I also inspected some of the other applications I have hosted to see if there was anything unusual there. Code injections or user creation, for example. I didn’t see anything.

Then I did step 4 for each of the sites. Wordress provides a “SALT CODE GENERATOR” at https://api.wordpress.org/secret-key/1.1/salt/ which gives you a code block suitable for adding to wp-config.php easily. What is the Salt? I let the WordPress documentation tell you:

In Version 2.6, three (3) security keys, AUTH_KEY, SECURE_AUTH_KEY, and LOGGED_IN_KEY, were added to ensure better encryption of information stored in the user’s cookies. These collectively replaced a single key introduced in Version 2.5.
In Version 2.7 a fourth key, NONCE_KEY, was added to this group. When each key was added, corresponding salts were added: AUTH_SALT, SECURE_AUTH_SALT, LOGGED_IN_SALT, and NONCE_SALT.

You don’t have to remember the keys, just make them long, random and complicated — or better yet, use the online generator. You can change these at any point in time to invalidate all existing cookies. This does mean that all users will have to login again.

A secret key makes your site harder to hack by adding random elements to the password.

In simple terms, a secret key is a password with elements that make it harder to generate enough options to break through your security barriers. A password like “password” or “test” is simple and easily broken. A random, long password which uses no dictionary words, such as “88a7da62429ba6ad3cb3c76a09641fc” would take a brute force attacker millions of hours to crack. A ‘salt‘ is used to further enhance the security of the generated result.

I’ve not seen any recurrence of the suspicious behavior and have not seen any attempted entry by any of the “backup” accounts created.

There’s no common themes or plugins (other than WordFence and WordPress and my own host) to link the intrusions but I’ll remain vigilant. When I wrote “WordFence is vital for self-hosted WordPress instances” the other day this is the kind of thing I was thinking of.

I reported the behavior to my web host, which they appreciated. I had blocked the IP address for all my sites from that host which they verified I did correctly. They also showed the logs of the logins and other than dates and times not much was useful other than a User-Agent of Mozilla/5.0 (Windows NT 6.1;
WOW64; rv:37.0) Gecko/20100101 Firefox/37.0
.

Because it was an EC2 instance that was at the originating IP address, I also collected my notes on the behavior and reported it to Amazon Web Services: AWS: Report Abuse.

On 21 February 2018 I received replies from Amazon. Not particularly satisfying but it’s my hope they’ll continue to take security seriously.

Hello,

Thank you for submitting your abuse report. We have begun our investigation into the source of the activity or content you reported.

We’ve determined that an Amazon EC2 instance was running at the IP address you provided in your abuse report. We have reached out to our customer to determine the nature and cause of this activity or content in your report.

We will investigate your complaint to determine what additional actions, if any, need to be taken in this case. Due to our privacy and security policies, we cannot provide details regarding the resolution of this case, or the identity of our customer. We may notify you during our investigation if our customer requires more information from you to complete their troubleshooting of the issue. Our customer may reply stating that the activity or content is expected and instructions on how to prevent the activity or manually remove the content, as well. If you wish to provide additional information to us or our customer regarding this case, please reply to this email.

Please note that if we determine the activity or content to not be abusive, we will notify you and resolve the case; we may refrain from communicating further, in that case.

We will notify you once this case has been marked resolved. Thank you for alerting us to this issue.

Regards,
AWS Abuse Team

And also this, which resolves the closes the case out:

Hello,

This is a follow up regarding the abusive content or activity report that you submitted to AWS. We have investigated this report, and have taken steps to mitigate the reported abusive content or activity. Due to our privacy and security policies we are unable to provide details regarding the resolution of this case or the identity of our customer.

We are committed to mediating reports of abusive content or activity to the satisfaction of both the reporters and our customers. If you believe the reported content or activity persists, or are not satisfied with the resolution of this case, please reply directly to this message with more information. Your response should include the most recent activity logs or web location of the content that you have available that indicates that the activity or content persists, as well as a clear, succinct explanation of what you expect of us and our customer.

Thank you for bringing this matter to our attention.

Regards,
AWS Abuse Team

I hope this proves useful to folks. If you’re running self-hosted WordPress, do take a serious look at WordFence.

Markov Chains are hilarious. 2018 Feb 23

I’ve wanted to make Markov chain generated sentences based on this blog for a long while. Wednesday night, I did. It took me under an hour! Why have I avoided it thinking it’d be difficult? Probably I thought it’d take a long time and would be lame.

NOT SO

First, I exported the contents of my blog: Tools > Export

Out of that, you get a complete dump of your site’s content. This is a WordPress eXtended RSS file. What we care about are just two things from each post: the title and the content. To turn this XML into text I wrote a bit of PHP. It parses the <item> elements and then does a bit of string manipulation to remove all the HTML tags. It then dumps it into a file called “artlung.corpus.txt”.

<?php
  $xmlstr = file_get_contents("artlung.wordpress.2018-02-22.xml");
  $outputfilename = "artlung.corpus.txt";
  $blogcontent = new SimpleXMLElement($xmlstr);
  $all_text = array();
  $i = 0;
  foreach ($blogcontent->channel->item as $item) {
    $content = $item->children('content', true);
    $content = str_replace('>', "> ", $content);
    $content = str_replace('\n', " ", $content);
    $all_text[] = (strip_tags($item->children('content', true)));
    $all_text[] = ((string)$item->title);
  }
  $str = implode("\n", $all_text);
  file_put_contents($outputfilename, $all_text);
?>

(I ran this locally on my Mac since I have PHP installed. Did you know you can run a one-line PHP server? Just run php -S localhost:8000 and you have a local web server! I use it all the time. Read about it here.

Then I talked to my friend Kelly and asked her about what library I might use to accomplish this task. She pointed me to NLP (Natural Language Processing) libraries. I did a bit of googling and found Markovify: “a simple, extensible Markov chain generator.” It seems very well documented and the README on GitHub had easy install instructions. I already had python and pip installed and a terminal session with sudo pip install markovify did the trick.

Once I did that, I created a file “artlungmarkovify.py” and put this in it:

import markovify

# Get raw text as string.
with open("artlung.corpus.txt") as f:
    text = f.read()

# Build the model.
text_model = markovify.Text(text)

# Print five randomly-generated sentences
for i in range(10):
    print(text_model.make_sentence())

# Print three randomly-generated sentences of no more than 140 characters
for i in range(3):
    print(text_model.make_short_sentence(140))

Then I ran python artlungmakovify.py in terminal and BOOM! There’s some not-quite-Joe-Crawford blog sentences (every other sentence italicized to help distinguish the lines):

I expect she’ll be blogging about the interests of governance vs. conservative media in David Frum: Waterloo: I’ve been working at Yahoo has.
Still amazed we made together.
Nobody cares if you know it.
Immersed in his last name while he asked me that if life were these: Joe Crawford | Joe in LeahPeah’s GlassesNice picture, eh?world, meet olivia rex.
When I tend to ramble a bit, pulled nonnative plants, planted native ones.
Also, my feet and went with following the instructions on the NYTimes website Ted Koppel grills FEMA head Mike Brown.
Perhaps in expiating these exhibits we’ll actually find that when in 2004 and 2005.
Roth had a birthday card weighing one pound.

I then loaded up the file into BBEdit and did some cleanup. I removed duplicate lines, removed things like URLs. Sorted all the individual lines. I used BBEdit’s Markup > Utilities > Convert HTML to Text to undo the HTML entities that were there. I can see that a clean set of sentences are important for getting a good Markov result.

Now I have it generating lines like:

I think of the world of connections: Online social networks are powerful.
I left them in town.
This tension and disquietude sometimes spiral out of steak, chicken, pasta, and pretty much Nazis and haven’t caught on that beach, and the like.
People all over it.
I checked in at the cover here.
I don’t really care for that hair under your belt.
Last Friday, just 3 days to come.
Remembrances all over the weekend.
I’ve been blogging since before I was not particularly interested, but she generally agreed.
But it feels honest to do that, and I’m looking forward to with delight, fear, wonderment.
I’m going to tap my phones and tablets and e-readers shows us that it’s like I’m going to have never met her.
101 in 16 years for a logo, and right there for the stage.
As it is to say, the whole family is way out at subway stops.
My Grandfather retired and they don’t have an original design vinyl giant robot.
I’m doing lots of orange groves back here.
Clever folks will realize you can get to the rock line.
It’s been a few dozen people in this house in which he invited every passerby to lie in the surf, another from yesterday.
The fact that my increased notoriety brings more candy, I expect we won’t get to do serious work.
It will cost $1743 to fix the toilet which was leaking.I have posted in the meantime.A few weeks ago at an unexpected angle – young, white, female and with each player serving in turn.
Yes, San Diego Blog Meetup — Calling all Web Designers in San Diego very dearly.
Who else gets cool Swedish web developers take the train?
But the show must go to the car windows unrolled when the receiver to participate in a much less here.
It was a contest that year to year quickly.
If I finish a silly Flash game I want one of those old images.
It strikes me as a teen, working in Hollywood.

I love this. It’s entertaining silliness.

Now, I sent a few sentences to Leah and she said “it sounds a bit too much like President Trump”–which admittedly made me rather sad. But I can see that with a good corpus some rather interesting things might come out of it. My friend Kelly on reading some results said “It’s very interesting. Like a semantic word cloud.”

It really feels like this century will have more things like this. At some point computers will so good at mimicking us that we won’t be able to tell the difference. What that means for us as a culture? Hard to say.

I blogged for 17 years and all I got were these lousy Markov chains. 2018 Feb 26

On Friday I wrote about how I turned 17 years of blog text into interesting sentences. I’ve also put that up on the web at lab.artlung.com/bloggingbot and now, with the help of Cheap Bots Done Quick (a free bot hosting service created by George Buckenham).

I turned that into a Twitter bot that tweets regularly. You can follow it at @BloggingBot.

I really like the code CBDQ uses: Tracery. It’s a straightforward, JavaScript-like syntax that’s kind of fun to write. It’s the brainchild of GalaxyKate.

{ 
"sentences": ["Here are videos of some of Leah's brothers and sisters.",
"Trying to get back on the horse, and I suppose I'm glad I don't get seasick.",
// 10,000 lines of pre-generated Markovify sentences
"If there are fewer, but still a long way to go. from Instagram IFTTTHere for kind of a joke as a band."],
"option": ["You asked for it!", "Here you go!", "Yes indeed!"],
"origin" : "#sentences#"
}

It’s free to host! Now, previously I’d written about @Ventcheck a bot I wrote at San Diego Code Kitchen in 2016.

BloggingBot can answer a reply made to it, because CBDQ has added that functionality. The reply Tracery code is nice too:

{
	"more please":"#option#\n\n#origin#\n\nThanks you for your kind attention. cc @artlung",
	".":"Hiya. I'm just a bot. But if you answer with \"more please\" then I'll tweet you again. :-)"
}

I submitted it to Mefi Projects yesterday. I look forward to having more projects to submit there. Metafilter is a great community.

So if you feel inclined, please feel free to follow @BloggingBot

I’m enjoying trying to write something technical every day. It’s a challenge that feels doable.

Thanks for your kind attention.

Color the Smiley 2018 Feb 27

Over the years I have made a lot of little web experiments and geegaws. I’ve made hangman games and drawing programs and random text generators. At one place I worked I helped make a thing that would turn an uploaded photo of a face into a Terminator face!

I’ve made so many of these kind of things I don’t always remember I’ve made them. Enter the Smiley!

I remember, vaguely, building this. I don’t have a record of when I did. I include a link to my twitter feed but I can’t find a tweet about it. I joined twitter in 2006 so it could be anytime then. The code is the best source of clues:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>

The usage of jQuery 1.4.2 is the tell. Version 1.5 came out on January 31, 2011, and 1.4 was a year earlier. So 2010 is a good bet. 2010 had a lot of things going on. It happens to be the year my mother was so sick, and died. I think that’s why I never wrote about it.

But what about the code?

$(document).ready(function(){
	$('#controls span').bind('click mouseover focus', function(){
		$(this).siblings().removeClass('selected');
		$(this).addClass('selected');

		var fig = $('span.selected:lt(3)').text();
		var grd = $('span.selected:gt(2):lt(6)').text();
		
		$('div#wrapper, .smiley div.figure').css('background-color', '#' + fig);
		$('.smiley, .smiley div.ground').css('background-color', '#' + grd);
		
		location.hash = '#' + fig + '' + grd;
		return false;
	});

	var colors = location.hash.split('#')[1];
	for(var i=0;i<colors.length;i++){
		$('div.segment div:eq('+i+') span:contains('+colors.substr(i,1)+')').trigger('click');
	}
	
});
</script>

The code is not bad! It does the job, it uses idiomatic jQuery in a way I might today. I’d probably organize the whole thing differently now but it’s a fun little snippet. These days I might play with in such a way that you could share the silly smiley with people on social media. I might add a feature to turn it into an image. I might change the interaction a bit – I do have the numerical color value buttons respond to mouseover and click, so users on a phone or tablet don’t have a bad time. I also made it very narrow, also friendly to phones of the time.

Now, I can tell by the CSS I didn’t use SASS or any other CSS Preprocessor so that’s a bummer there. I also think I’d organize the code in a more MVC way so that the color model could be reused for something else.

Thanks for reading.

January 2018 ←Before After→ March 2018