Dabitch.net - Everything is so random there must be a pattern

Hi, I'm Åsk, I'm a geeky creative director. Here I share whatever is on my mind and the occasional script.

Dabitch.net - Everything is so random there must be a pattern

Cleaning Twitter by unfollowing, to reset your follows/following flow.

Cleaning Twitter by unfollowing, to reset your follows/following flow.

Sometimes a Twitter cleanse is necessary, as the Twitter app has some odd bugs in it and acts up from time to time. It'll suddenly bury your close friends and only show you news articles. It'll unfollow close friends without telling you. Out of curiosity, I wanted to find out who the first person to follow me was, and who the first person that I followed was.

To figure this out, go to your Twitter profile page, and click either "following" or "followers", and then open your javascript console under "View > Developer > Javascript Console". Once there, copy and paste this little nugget and scroll back to the very first tweep who followed/you followed. While you are down there in the very last page of scrolling back, you may find your pals that you never see these days, and you can check their pages, "like" some of their tweets, reply to recent stuff, unfollow&follow and whatnot to coax twitter into showing you them more often.

var ScrollTimer;
window.onclick = function () { clearInterval(ScrollTimer) }
ScrollTimer = setInterval(()=> { scrollTo(0, document.body.scrollHeight);console.log(document.body.scrollHeight) }, 500);

This is fun, you may find that you've not seen or interacted with these people in a bit. Which brings me to the next fix that I have. Mass unfollowing those who don't follow you. This may seem a bit excessive, after all you are not the type who only wants to follow people who follow you, but in the case of my account @adland I do actually want to engage with my real audience and see what they say. And Adland was following almost 20K people! Ugh! What to do?

Same story, roll over to your twitter profile and "following", then open View > Developer > Javascript Console".
Then prepare to be rate limited if you follow as many as @adland does because this is what you'll paste in your window now. This script is from jalbam on Github and is called unfollow-non-followers-twitter.js.
Note that you can establish a limit for the unfollow actions performed (per cycle and also in total) by editing the 'MAXIMUM_UNFOLLOW_ACTIONS_PER_CYCLE' and 'MAXIMUM_UNFOLLOW_ACTIONS_TOTAL' variables and I recommend that you do so if you have a large account.

/*
	Unfollow (stop following) those people who are not following you back on Twitter (or unfollow everyone if desired).
	
	This will work for new Twitter web site code structure (it was changed from July 2019, causing other unfollow-scripts to stop working).
	
	Instructions:
	1) The code may need to be modified depending on the language of your Twitter web site:
		* For English language web site, no modification needed.
		* For Spanish language web site, remember to set the 'LANGUAGE' variable to "ES".
		* For another language, remember to set the 'LANGUAGE' variable to that language and modify the 'WORDS' object to add the words in that language.
	2) Optionally, you can edit the 'SKIP_USERS' array to insert those users that you do not want to unfollow (even if they are not following you back).
	3) If you want to follow everyone (except the users in 'SKIP_USERS'), including those who are following you, just set the 'UNFOLLOW_FOLLOWERS' variable to 'true'.
	4) You can set the milliseconds per cycle (each call to the 'performUnfollow' function) by modifying the 'MS_PER_CYCLE' variable.
	5) If desired, set a number to the 'MAXIMUM_UNFOLLOW_ACTIONS_PER_CYCLE' variable to establish a maximum of unfollow actions to perform for each cycle (each call to the 'performUnfollow' function). Set to null to have no limit.
	6) If desired, set a number to the 'MAXIMUM_UNFOLLOW_ACTIONS_TOTAL' variable to establish a maximum of unfollow actions to perform in total for all cycles (all calls to the 'performUnfollow' function). Set to null to have no limit.
	7) When the code is fine, on Twitter web site, go to the section where it shows all the people you are following (https://twitter.com/YOUR_USERNAME_HERE/following).
	8) Once there, open the JavaScript console (F12 key, normally), paste all the code there and press enter.
	9) Wait until you see it has finished. If something goes wrong or some users were not unfollowed, reload the page and repeat from the step 8 again.
	
	* Gist by Joan Alba Maldonado: https://gist.github.com/jalbam/d7678c32b6f029c602c0bfb2a72e0c26
*/


var LANGUAGE = "EN"; //NOTE: change it to use your language!
var WORDS =
{
	//English language:
	EN:
	{
		followsYouText: "Follows you", //Text that informs that follows you.
		followingButtonText: "Following", //Text of the "Following" button.
		confirmationButtonText: "Unfollow" //Text of the confirmation button. I am not totally sure.
	},
	//Spanish language:
	ES:
	{
		followsYouText: "Te sigue", //Text that informs that follows you.
		followingButtonText: "Siguiendo", //Text of the "Following" button.
		confirmationButtonText: "Dejar de seguir" //Text of the confirmation button. I am not totally sure.
	}
	//NOTE: if needed, add your language here...
}
var UNFOLLOW_FOLLOWERS = false; //If set to true, it will also remove followers (unless they are skipped).
var MS_PER_CYCLE = 10; //Milliseconds per cycle (each call to 'performUnfollow').
var MAXIMUM_UNFOLLOW_ACTIONS_PER_CYCLE = null; //Maximum of unfollow actions to perform, per cycle (each call to 'performUnfollow'). Set to 'null' to have no limit.
var MAXIMUM_UNFOLLOW_ACTIONS_TOTAL = null; //Maximum of unfollow actions to perform, in total (among all calls to 'performUnfollow'). Set to 'null' to have no limit.
var SKIP_USERS = //Users that we do not want to unfollow (even if they are not following you back):
[
	//Place the user names that you want to skip here (they will not be unfollowed):
	"user_name_to_skip_example_1",
	"user_name_to_skip_example_2",
	"user_name_to_skip_example_3"
];
SKIP_USERS.forEach(function(value, index) { SKIP_USERS[index] = value.toLowerCase(); }); //Transforms all the user names to lower case as it will be case insensitive.

var _UNFOLLOWED_TOTAL = 0; //Keeps the number of total unfollow actions performed. Read-only (do not modify).

//Function that unfollows non-followers on Twitter:
var performUnfollow = function(followsYouText, followingButtonText, confirmationButtonText, unfollowFollowers, maximumUnfollowActionsPerCycle, maximumUnfollowActionsTotal)
{
	var unfollowed = 0;
	followsYouText = followsYouText || WORDS.EN.followsYouText; //Text that informs that follows you.
	followingButtonText = followingButtonText || WORDS.EN.followingButtonText; //Text of the "Following" button.
	confirmationButtonText = confirmationButtonText || WORDS.EN.confirmationButtonText; //Text of the confirmation button.
	unfollowFollowers = typeof(unfollowFollowers) === "undefined" || unfollowFollowers === null ? UNFOLLOW_FOLLOWERS : unfollowFollowers;
	maximumUnfollowActionsTotal = maximumUnfollowActionsTotal === null || !isNaN(parseInt(maximumUnfollowActionsTotal)) ? maximumUnfollowActionsTotal : MAXIMUM_UNFOLLOW_ACTIONS_TOTAL || null;
	maximumUnfollowActionsTotal = !isNaN(parseInt(maximumUnfollowActionsTotal)) ? parseInt(maximumUnfollowActionsTotal) : null;
	maximumUnfollowActionsPerCycle = maximumUnfollowActionsPerCycle === null || !isNaN(parseInt(maximumUnfollowActionsPerCycle)) ? maximumUnfollowActionsPerCycle : MAXIMUM_UNFOLLOW_ACTIONS_PER_CYCLE || null;
	maximumUnfollowActionsPerCycle = !isNaN(parseInt(maximumUnfollowActionsPerCycle)) ? parseInt(maximumUnfollowActionsPerCycle) : null;
	
	//Looks through all the containers of each user:
	var totalLimitReached = false;
	var localLimitReached = false;
	var userContainers = document.querySelectorAll('[data-testid=UserCell]');
	Array.prototype.filter.call
	(
		userContainers,
		function(userContainer)
		{
			//If we have reached a limit previously, exits silently:
			if (totalLimitReached || localLimitReached) { return; }
			//If we have reached the maximum desired number of total unfollow actions, exits:
			else if (maximumUnfollowActionsTotal !== null && _UNFOLLOWED_TOTAL >= maximumUnfollowActionsTotal) { console.log("Exiting! Limit of unfollow actions in total reached: " + maximumUnfollowActionsTotal); totalLimitReached = true; return;  }
			//...otherwise, if we have reached the maximum desired number of local unfollow actions, exits:
			else if (maximumUnfollowActionsPerCycle !== null && unfollowed >= maximumUnfollowActionsPerCycle) { console.log("Exiting! Limit of unfollow actions per cycle reached: " + maximumUnfollowActionsPerCycle); localLimitReached = true; return;  }
			
			//Checks whether the user is following you:
			if (!unfollowFollowers)
			{
				var followsYou = false;
				Array.from(userContainer.querySelectorAll("*")).find
				(
					function(element)
					{
						if (element.textContent === followsYouText) { followsYou = true; }
					}
				);
			}
			else { followsYou = false; } //If we want to also unfollow followers, we consider it is not a follower.

			//If the user is not following you (or we also want to unfollow followers):
			if (!followsYou)
			{
				//Finds the user name and checks whether we want to skip this user or not:
				var skipUser = false;
				var userName = "";
				Array.from(userContainer.querySelectorAll("[href^='/']")).find
				(
					function (element)
					{
						if (skipUser) { return; }
						if (element.href.indexOf("search?q=") !== -1 || element.href.indexOf("/") === -1) { return; }
						userName = element.href.substring(element.href.lastIndexOf("/") + 1).toLowerCase();
						Array.from(element.querySelectorAll("*")).find
						(
							function (subElement)
							{
								if (subElement.textContent.toLowerCase() === "@" + userName)
								{
									if (SKIP_USERS.indexOf(userName) !== -1)
									{
										console.log("We want to skip: " + userName);
										skipUser = true;
									}
								}
							}
						);
					}
				);
				
				//If we do not want to skip the user:
				if (!skipUser)
				{
					//Finds the unfollow button:
					Array.from(userContainer.querySelectorAll('[role=button]')).find
					(
						function(element)
						{
							//If the unfollow button is found, clicks it:
							if (element.textContent === followingButtonText)
							{
								console.log("* Unfollowing: " + userName);
								element.click();
								unfollowed++;
								_UNFOLLOWED_TOTAL++;
							}
						}
					);
				}
			}
		}
	);
	
	//If there is a confirmation dialog, press it automatically:
	Array.from(document.querySelectorAll('[role=button]')).find //Finds the confirmation button.
	(
		function(element)
		{
			//If the confirmation button is found, clicks it:
			if (element.textContent === confirmationButtonText)
			{
				element.click();
			}
		}
	);
	
	return totalLimitReached ? null : unfollowed; //If the total limit has been reached, returns null. Otherwise, returns the number of unfollowed people.
}


//Scrolls and unfollows non-followers, constantly:
var scrollAndUnfollow = function()
{
	window.scrollTo(0, document.body.scrollHeight);
	var unfollowed = performUnfollow(WORDS[LANGUAGE].followsYouText, WORDS[LANGUAGE].followingButtonText, WORDS[LANGUAGE].confirmationButtonText, UNFOLLOW_FOLLOWERS, MAXIMUM_UNFOLLOW_ACTIONS_PER_CYCLE, MAXIMUM_UNFOLLOW_ACTIONS_TOTAL); //For English, you can try to call it without parameters.
	if (unfollowed !== null) { setTimeout(scrollAndUnfollow, MS_PER_CYCLE); }
	else { console.log("Total desired of unfollow actions performed!"); }
};
scrollAndUnfollow();

As you can see, it's easily tweakable to follow everyone, instead of unfollowing, if that is what you would like to achieve instead.

I ran this on @adland's account and unfollowed almost 5000 users who were not following adland, which was great because I had noticed a lot of spam and botlike behavior in my adland feed which was making it quite useless to me.

Encouraged by this, I pulled the same trick on my @dabitch account, and while the number of accounts I unfollowed was only a couple of hundred, it drastically changed my feed there as well. I had followed a lot of news sources, unfollowing them allowed for people to show up rather than "AP" or whathaveyou, making it much friendlier at once.
But then I also began to see complete strangers and obvious bot accounts. I checked their pages, they were following me, I was following them back, and their accounts were established years ago like 2009. Yet the accounts were obvious one-topic bots, or retweet bots, and the avatars, locations and names didn't look familiar to me at all. I wonder if people have had their accounts hijacked, or if there is a black market for accounts with enough followers to be sold to clear twitter-bot runners. 🤔

If you want to make a list of people who you follow, or who are not following you, Jalbam on Github made a bit of code for that too! Then you can copy the names and add to a list! Here's the code for that.

/*
	Show user names of people you are following on Twitter, being able to choose certain filters to skip some users (and even skip followers or non-followers).
	
	This will work for new Twitter web site code structure (it was changed from July 2019).
	
	Instructions:
	1) The code may need to be modified depending on the language of your Twitter web site:
		* For English language web site, no modification needed.
		* For Spanish language web site, remember to set the 'LANGUAGE' variable to "ES".
		* For another language, remember to set the 'LANGUAGE' variable to that language and modify the 'WORDS' object to add the words in that language.
	2) If you do not want to print information about whether the user is following you or not, set the 'PRINT_FOLLOW_INFORMATION' variable to false.
	3) Optionally, you can edit the 'SKIP_USERS' array to insert those users whose names you do not want to print.
	4) To skip (do not print) users who are following you, set the 'SKIP_FOLLOWERS' variable to true. Both 'SKIP_FOLLOWERS' and 'SKIP_NON_FOLLOWERS' variables cannot be set to true at the same time.
	5) To skip (do not print) users who are not following you, set the 'SKIP_NON_FOLLOWERS' variable to true. Both 'SKIP_FOLLOWERS' and 'SKIP_NON_FOLLOWERS' variables cannot be set to true at the same time.
	6) You can set the milliseconds per cycle (each call to the 'printUserNames' function) by modifying the 'MS_PER_CYCLE' variable.
	7) When the code is fine, on Twitter web site, go to the section where it shows all the people you are following (https://twitter.com/YOUR_USERNAME_HERE/following).
	8) Once there, open the JavaScript console (F12 key, normally), paste all the code there and press enter.
	9) Wait until you see it has finished. If something goes wrong or some users were not printed, reload the page and repeat from the step 8 again.
	
	* Gist by Joan Alba Maldonado: https://gist.github.com/jalbam/1546b944f5074efd20e5bc838ee138f5
*/


var LANGUAGE = "EN"; //NOTE: change it to use your language!
var WORDS =
{
	//English language:
	EN:
	{
		followsYouText: "Follows you" //Text that informs that follows you.
	},
	//Spanish language:
	ES:
	{
		followsYouText: "Te sigue" //Text that informs that follows you.
	}
	//NOTE: if needed, add your language here...
}
var MS_PER_CYCLE = 10; //Milliseconds per cycle (each call to 'printUserNames').
var PRINT_FOLLOW_INFORMATION = true; //Sets whether to also print information about whether the user follows you or not.
var SKIP_FOLLOWERS = false; //Defines whether to avoid printing user names of followers.
var SKIP_NON_FOLLOWERS = false; //Defines whether to avoid printing user names of non-followers.
var SKIP_USERS = //Users whose name we do not want to print:
[
	//Place the user names that you want to skip here (they will not be printed):
	"user_name_to_skip_example_1",
	"user_name_to_skip_example_2",
	"user_name_to_skip_example_3"
];
SKIP_USERS.forEach(function(value, index) { SKIP_USERS[index] = value.toLowerCase(); }); //Transforms all the user names to lower case as it will be case insensitive.

//Function that names of the users that you are following on Twitter:
var USERS_PRINTED = {}; //Object that will keep the user names printed already and information about whether they are following you or not.
var printUserNames = function(followsYouText, skipFollowers, skipNonFollowers, printFollowInformation)
{
	followsYouText = followsYouText || WORDS.EN.followsYouText; //Text that informs that follows you.
	skipFollowers = (skipFollowers === true || skipFollowers === false) ? skipFollowers : SKIP_FOLLOWERS;
	skipNonFollowers = (skipNonFollowers === true || skipNonFollowers === false) ? skipNonFollowers : SKIP_NON_FOLLOWERS;
	printFollowInformation = (printFollowInformation === true || printFollowInformation === false) ? printFollowInformation : PRINT_FOLLOW_INFORMATION;
	
	if (skipFollowers && skipNonFollowers) { console.log("You cannot skip printing everyone!"); return; }
	
	//Looks through all the containers of each user:
	var userContainers = document.querySelectorAll('[data-testid=UserCell]');
	Array.prototype.filter.call
	(
		userContainers,
		function(userContainer)
		{
			//Checks whether the user is following you:
			var followsYou = false;
			Array.from(userContainer.querySelectorAll("*")).find
			(
				function(element)
				{
					if (element.textContent === followsYouText) { followsYou = true; }
				}
			);

			if (followsYou && skipFollowers) { return; }
			else if (!followsYou && skipNonFollowers) { return; }

			//Finds the user name and checks whether we want to skip this user or not:
			var skipUser = false;
			var userName = "";
			Array.from(userContainer.querySelectorAll("[href^='/']")).find
			(
				function (element)
				{
					if (skipUser) { return; }
					if (element.href.indexOf("search?q=") !== -1 || element.href.indexOf("/") === -1) { return; }
					userName = element.href.substring(element.href.lastIndexOf("/") + 1).toLowerCase();
					Array.from(element.querySelectorAll("*")).find
					(
						function (subElement)
						{
							if (subElement.textContent.toLowerCase() === "@" + userName)
							{
								if (SKIP_USERS.indexOf(userName) !== -1)
								{
									skipUser = true;
								}
							}
						}
					);
				}
			);
			
			//If we do not want to skip the user:
			if (!skipUser)
			{
				//Prints the username:
				if (!USERS_PRINTED[userName])
				{
					console.log("* Username: " + userName + (PRINT_FOLLOW_INFORMATION ? (followsYou ? " follows you" : " does NOT follow you") : ""));
					USERS_PRINTED[userName] = { userName: userName, followsYou: followsYou };
				}
			}
		}
	);
}


//Scrolls and prints usernames, constantly:
var scrollAndShowUsernames = function()
{
	if (SKIP_FOLLOWERS && SKIP_NON_FOLLOWERS) { console.log("You cannot skip printing everyone!"); return; }
	window.scrollTo(0, document.body.scrollHeight);
	printUserNames(WORDS[LANGUAGE].followsYouText, SKIP_FOLLOWERS, SKIP_NON_FOLLOWERS, PRINT_FOLLOW_INFORMATION); //For English, you can try to call it without parameters.
	setTimeout(scrollAndShowUsernames, MS_PER_CYCLE);
};
scrollAndShowUsernames();

Ju mer hat från start, desto bättre

Ju mer hat från start, desto bättre

Denna krönika publicerades i Resumé nr 19–20 den 19 maj 2016

En logotyp har designats om. Pånyttfödd möter den världen i glassiga färger och alla från Tokyo till Haparanda har en åsikt om hur den ser ut. Skämtbilder och memes sprids lika fort som artiklar om logotyp-bytet. Appanvändarna reagerar som om de just varit hos frisören och helt oförberett fått en helt ny frisyr, fullständigt olik alla andra de någonsin har haft. Alla tar det personligt.

Vi har reagerat så här i åratal, jag var hemskt upprörd när UPS tog bort Paul Rands logoklassiker och snöret på paketet, bara för att bli en sköld bland tusen sköldar.

Ibland känns det som om en ny logotyp är som scenen i Carrie, där hon skall kröna balens drottning men får grisblod hällt på sig och alla skrattar åt henne.

Jag har själv varit med i stora varumärkesförändringar, och varje liten detalj har diskuterats och presenterats i evigheter innan slutresultat klubbats. Man får en enorm lust att förklara för alla varför vissa beslut har tagits när det stormas kring en ny stil. Misstaget är att tro att de högljudda är majoriteten. Skojfriska skämtbilder på twitter är helt enkelt en social allergisk reaktion mot det nya, man tar sig friheter att skämta, och syns därmed själv i ”debatten”. Om den första häller grisblod – det vill säga klankar ned – så hänger alla andra med på det spåret.

Sen, när allt lugnat ned sig brukar folk helt enkelt vänja sig. Nytt är fräscht. Nytt är modernt. Nytt känns rent, som en vårstädning. Nya stilar påverkar andra, som när iOS8 blev ”platt” och alla appars logotyper gjorde samma.

Till och med Telia, som man tyckte var så märklig och påminde om Thai Air och hade helt fel färg för 15 år sedan, har vuxit in i sin lila färgroll med sin gradvisa uppgradering och känns nu som en gammal barndomsvän som växte in i sitt ansikte och pottfrisyr. Det kanske är så, att ju mer folk hatar det från start, ju bättre blev förändringen.

Don't seek praise, seek criticism - and advice

Don't seek praise, seek criticism - and advice

I suppose this is as good of a spot as any to note that I gave some sincere advice to Nikky Gary regarding looking for work as a young creative. This has now become an article at Adpulp.

Don't be shy in seeking out a portfolio crit. If you develop a good portfolio crit relationship with one person and they ask you back in six months with an improved portfolio, jump on that goal and you may find yourself with a career mentor for years to come.

Dear Young Creatives, You Can Do This. Sincerely, A Young Creative.

Moving off S3 with Drupal 7

Moving off S3 with Drupal 7

It seemed a great idea to use S3, but after receiving a DMCA takedown request from them regarding a film I stored there, I knew that I needed to move. Ambulance-chasing lawyers who send such requests out strangle my choices.

Step one, download everything. Now this took several days, five but who is counting, and since I had to start over a few times, I was a little concerned about it. But it was pretty straightforward, just use the aws version of rsync.

First, install aws-cli on your MacOSX by opening up a terminal window and typing this

curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip" 
unzip awscli-bundle.zip 
sudo ./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws

Now check that you have it installed by asking what version you have:

aws --version

So you're set, now the best way to download everything, is to simply do it in one go.

aws s3 sync s3://b0wie /Volumes/5terabytes/b0wie

Like I said, it took me days to do and I downloaded it all into an external drive that I named 5Terabytes. With all of this solved, I just needed to upload this to my new fancy server, and make sure my Drupal 7 could find it.

That's where it gets a tiny bit more complicated. While it's simple enough to run a mysql command that switches all of your s3:// to public:// like this:

UPDATE `file_managed`
SET uri = REPLACE(uri, 's3://', 'public://')
WHERE uri LIKE ('s3://%');

This is not the only place in your Drupal 7 database where your files storage settings exist. So you should create your own database up date module, I created one that I called "updatedb" and placed it in the /sites/all/modules folder.

The first file, updatedb.info you could write whatever you like here I suppose

name = Update Database
description = Purpose is to run the hook_update on every release to implement one-time execution of code
core = 7.x
package = Custom

Next file, updatedb.install contains the fun stuff:

<?php

/**
 * @file
 * Install file for the Update Database module.
 */

/**
 * Brute force update of field sources to point to public from S3.
 */
function updatedb_update_7600($sandbox) {
  $results = db_query("
    select id, data
    from {field_config}
    where data like '%s3%'")
      ->fetchAll();
  foreach ($results as $result) {
    $data = unserialize($result->data);
    $data['settings']['uri_scheme'] = 'public';
    $data_serialized = serialize($data);

    db_update('field_config')
        ->fields(array('data' => $data_serialized))
        ->condition('id', $result->id)
        ->execute();
  }
}

You will also have to make a "updatedb.module" file, but you don't need to put anything real in it, so I just wrote:

<?php

/**
 * @file
 * Update Database module.
 */

/**
 * A module file must exist, therefore empty.
 */

Now you can turn on this module in your admin pages, just like you would any other module, and update your database. All the usual warnings, this will make changes in your database, make a backup first, all that jazz.

Once you've done all that, you can check that everything on your site is working. Turn off your s3 module, change your default file directory to files. Clear caches.

Your images might complain, this will be helped if you go to your structure > content types > manage fields. I had issues with my image field "widget type", but just changing that from media browser, to image (and save), and then back again sorted everything out. I had to do the same with a few more image fields that I had.

So that's how you leave S3 and return to local file hosting. Enjoy.


p.s. if you ever hardlinked anything, like I did in certain paragraph fields, you'll need to fix that too.

Figure out what fields you need to change, if you're not using paragraphs it will be in body and body_revision. You will do this:

update TABLE_NAME set FIELD_NAME =
replace(FIELD_NAME, 'Text to find', 'text to replace with');

In my case I had a paragraph fields, so I changed that and the revision.

update`field_data_field_mg_text_html_content`set`field_mg_text_html_content_value`=replace(`field_mg_text_html_content_value`,'://b0wie.s3.amazonaws.com/','://adland.tv/sites/default/files/')

Pretty straightforward.

Fixing that pesky "Parameter must be an array" error in PhPMyAdmin

Fixing that pesky "Parameter must be an array" error in PhPMyAdmin

I don't know who needs to hear this... Oh well, I do, because I forget things that I've done and this here blog is as good a place as any to put something that I might need to look up later.

When your PhPMyAdmin on Ubuntu Bionic Beaver (*giggle*) and PhP 7.2 keeps spitting out dumb errors on every page load, like this;

Warning in ./libraries/sql.lib.php#613 count(): Parameter must be an array or an object that implements Countable

You need to edit the sql.lib.php file, specifically you need to edit line 613.

sudo nano +613 /wherever/phpmyadmin/libraries/sql.lib.php

See this? Second line has a missing ")" after $analyzed_sql_results['select_expr'], and it has one extra after ['select_expr'][0] == '*'))) in the row below.

So change it to this:

((empty($analyzed_sql_results['select_expr']))
    || (count($analyzed_sql_results['select_expr']) == 1)
        && ($analyzed_sql_results['select_expr'][0] == '*'))

And then restart Nginx or whatever. Now you'll not have to see that error again.

You're not a diagnosis.

You're not a diagnosis.

When I was diagnosed with endometriosis, it had been a long, painful ride through many years and several countries' medical systems before I finally discovered what was so very wrong with me. I've been hospitalized in New York, taken to one by ambulance in London, been to emergency services in the Netherlands. It was a wild ride. Then, I lucked out with my OB/Gyn in Stockholm, and she discovered the root of all problems in a laparoscopy.

Endometriosis.

Armed with my new knowledge, I thought I could better help myself, but also hoped that I could help others. So I created support groups, engaged myself in associations, and pitched for better information brochures. I spent tonnes of creative time hoping I could "inform", and "raise awareness."
This went on for years, and at some point it took up far too much of my free time, and certainly hindered any creative prospects outside of the topic. As I met with another "endo-sister" one evening, a succesful executive whose shoes, purse, watch and car she drove to the meeting screamed "they pay me well", I realized that being all about my illness was preventing me from being me. Not only that, it was hampering my career, because I brought it up a lot.

"We are not our diagnosis" she said, "we're us."

That really stuck with me, and I had been fighting, I tried all sorts of treatments, I won't bore you with the details, but I had spent almost a decade trying to fix it and setting up support groups and talking about it, that my knowledge of my diagnosis was now a bigger time-suck than my diagnosis.

This reminded me of a girl that I knew in my class when I was primary school. She was a classic blond with that perfect wave-curl to her hair, big blue eyes, slightly taller than average girls and with a certain elegant ballet way to her outstretched hands. It was only when I was face to face with her the first time, that I realized that she was blind.

She was going to class with the rest of us, walking from our room out to breaks, and to lunch, and always with a couple of butterfly girlfriends hovering around her at every break.

In the morning, when us children would all be riding our bikes to school, I'd often end up riding in the same route at the same time as her. You see, she biked to school too, on a tandem bike. And she was the one in the front bike.

This was phenomally impressive to me, and I was slightly obsessed with the tandem bike itself. I had never been on one, and it looked like so much fun. I wanted to borrow it and ride and I had no qualms in announcing this to everyone.

Eventually I made friends with her, and she invited me to her house to play. We went to her room, and I commented on how lovely it was with all the baby blue and nice matching curtains. "Blue is my favorite color", she said, matter of factly. "But, how do you even know?" I asked, because kids don't care, they just ask. "I know that it's a cool, and calming color, and on the blue scale of things, then after that there's purple." she explained "I can see light and dark, I just can't see."

Fascinated I couldn't stop asking things; "You can see light and dark?"
"Yes, like, there are orange or red blobs, or dark spots, and then lighter areas. What do you see when you close your eyes? Maybe it's like that?" she concluded. My mind sufficently blown, she then asked me to come with her to school. This meant that I was allowed to come on the tandem bicycle.

When I arrived that morning, it was incredibly foggy. A proper white fog. The kind people call "pea soup". So as we rode, and we would hear other people on bikes nearby we'd yell their names to check if it was any of our friends. "Is that you, Ylvali?" "Yes!" "I hear some rusty chain that sounds like it needs oiling, that has to be Liselotte on her DBS bike!" muffled giggles in reply.

We took our shortcut, the same one that I took every day, across the gravel football field. Except today was so foggy, and I was on a tandembike, and she was in front of me in control. Which was just as well, really, since I couldn't see, but I could hear as Johan from the street on the left rode up with his BMX bike because he had to peddle much harder than anyone else and it made so much noise on the gravel. I'll never forget how it felt, cycling that space at that speed, with the fog surrounding us like a wall of white.

Fifteen plus years later, I was reading a local-ish magazine of some sort. A black and white photo of a thirty-something blond with long wavy hair and elegant hands caught my eye. On one hip she had a one year old baby smiling at the camera, at her feet she had a toddler laughing.

The article it turns out, was about how her city, my former home town, had wanted to "handle her children for her", since she was blind. She would not accept this, and showed the social services at every visit that they made to her house, how perfectly capable she was. And with this she had won a case against the city, and was allowed to care for her babies without assistance.

She was certainly not her diagnosis. "Blind" isn't who she is.

While I was initially just excited to see that she was doing well, having cute babies and living in her own house with her husband, she now haunts me every time someone announces a diagnosis.

While I can understand the relief, "I have just learned that I have ADHD, this explains so much regarding the problems I have had..." this moment can not become what defines you.

What defined my friend was that she always knew what she was doing, and was in control. Not her blindness.

What I've learned on this journey of both life and career, isn't just that "we are not our diagnosis", but how you react to having one will change everything.

If you let your diagnosis define you forever, then you are forever stuck.
A diagnosis is a tool, not a badge. The minute you let a disorder define you, is the minute you lose yourself and all your potential.

Mountain House - print campaign

Mountain House - print campaign

When there is a pandemic and you're eating freeze-dried meals, you may find that you suddenly have a campaign idea. At least we did, so we approached Mountain House with a storied history of providing MRE's for the armed forces back in the 70's. They are also big with campers, as well as people who plan for long-term emergencies. Since we're sick of the "we're all in this together" messaging and are desperately in need of a laugh right now, we decided to make these funny.

Art Direction: Åsk Wäppling
Copy: Evan brown

Art Direction wise I decided to lift the seventies retro look of the logo, and bring it as a frame to the lomo-fied images.

Bye Drupal 8.

Bye Drupal 8.

I don't think I can even begin to explain how much I despise Drupal 8.

It's not like I haven't given it a chance. I've set up at least five different websites with it, but every time there is a security upgrade, I spend hours trying to figure out why I am running into issues.

I've even built a shop and site for a client – two, in fact, but she didn't like the first one and while she liked the second one, the backend literally crumbled when I did a security upgrade-- so I have given it a fair shot. And I knew I would never move adland to it. So when my news alerts told me this morning to get on Drupal 8 NOW because Drupal 9 is coming I literally nuked my portfolio and shop here from orbit, and put this in its place.

This is powered by Ghost, and this will do just fine for me right now. I could tell you to use Drupal modules to convert and export markdown, or
use composer to do so, or create an archive with migrate or source CSV, but after my most recent security issues, none of these modules worked and I just pulled my limited data straight from mysql, so you're on your own. Sorry.

Great! You’ve successfully signed up.

Welcome back! You've successfully signed in.

You've successfully subscribed to Dabitch.net - Everything is so random there must be a pattern.

Success! Check your email for magic link to sign-in.

Success! Your billing info has been updated.

Your billing was not updated.