Month: January 2018

Mailchimp’s Subscriber Hash

I learned something today. In sitting down to finish up my mailchimp functions, I wanted to create a mailchimp_remove_teacher_from_list(listname) function and a mailchimp_blanket_unsubscibe_teacher() function. I thought that, after my previous success, it would go quickly.

I was wrong.

Over here, in the docs, there’s reference to how to delete list members, which is what I basically want to do:

client.lists.members.delete(list_id=”, subscriber_hash=”)

I knew what a list_id was, but wasn’t sure what the subscriber_hash was. After a bit of Googleing (I thought I’d have to ask mailchimp for the hash) I found this page and was able to piece it together:

In previous versions of the API, we exposed internal database IDs eid and leid for emails and list/email combinations. In API 3.0, we no longer use or expose either of these IDs. Instead, we identify your subscribers by the MD5 hash of the lowercase version of their email address so you can easily predict the API URL of a subscriber’s data.

For example, to get the MD5 hash of the email address Urist.McVankab@freddiesjokes.com, first convert the address to its lowercase version: urist.mcvankab@freddiesjokes.com. The MD5 hash of urist.mcvankab@freddiesjokes.com is 62eeb292278cc15f5817cb78f7790b08.

In short, the subscriber_hash argument is something you produce at your end and use to look a subscriber up. There’s something elegant about it — you have no business accessing the subscriber if you don’t know the email address, already — but I needed some time to get it done.

Here’s how I did it:

import hashlib # A standard library that does hashes

# The following is in .lower() case because mailchimp forms
# hashes from lowercase strings.
# The .encode() method tagged on the end encodes it as a byte literal
email = request.user.email.lower().encode(encoding='utf-8)

# This uses the hashlib library to make the hash. The .hexdigest()
# seems to be about equivalent to str() [forgive me internet!]
hash = hashlib.md5(email).hexdigest()

client.lists.members.delete(list_id=list_id, subscriber_hash=hash)

This is not a complete solution. It basically tags onto my last post. At some point, I want to compend everything I do into something more universally applicable. When I do, I have no plans to keep it secret.

Advertisements

Forming a running habit

After writing about how surprisingly motivational the Google Fit weekly running goals are for me, I thought it’d be nice to post an update:

Screenshot_20180121-132845

It took quite a bit of work and more than once I caught myself saying “if I don’t get a run in, I’ll have to wait a long time to push an incomplete week out the other side.” (If that phrasing makes any sense.)

The result was me having more back-to-back runs in the week: generally one 5k and a 7k, and a long run on the weekend. Maybe it’s not the structured approach to running I’d been hoping for, but it’s running.

Glory Days

I think a lot about the song “Glory Days” and of the danger of becoming a person who lives in the past. (‘A lot’ in this context means at least half a dozen times in my life.) The thing is, I used to run pretty regularly and it’s weird for me to struggle to get something done that used to be so fundamental to me.

I can rationalize that my kids are getting bigger, that I’m doing more with them, that I didn’t use to try and code a website in the same off-time that used to be just for reading and running. Nonetheless, it’s important to me that I continue to be the kind of person that I want to be, rather than assuming that having once run a marathon means I get to claim “runner” status forever.

Adding Mailchimp actions to a Django model

As I get ready to try a second time to attract users, I decided to use MailChimp mailing lists to keep in touch with these users, as well as setting up some ‘tutorial’ emails at regular intervals. (I’m imagining something like “You’ve been using dynamic-efl.com for a week now, did you know you can do this to get more out of it?”)

To do this, I’d have to have code in Django that automatically signed members up. That means that this is my first attempt to work with an API, even by way of a library.

I decided to go with the mailchimp3 library and installed it in my virtualenv according to the instructions and set up some variables in my settings.py file.

# Mailchimp stuff
# Authentication
MAILCHIMP_LOGIN = 'login'
MAILCHIMP_KEY = '===>SECRET<==='

# The lists
MAILCHIMP_LISTS = {'welcome': 'listID',
                   'germany': 'listID',
                   'beta-testers': 'listID'}<span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			></span>

The idea here is that I’ll be able to iterate over the keys in the lists, if I ever need to check that the user is in all the lists (for example, removing a user should include removing him from all lists).

To that end, I added a function at the beginning of my models.py file. (This probably isn’t good form).

def mailchimp_get():
    """ Returns a logged-in mailchimp client """
    return MailChimp(settings.MAILCHIMP_LOGIN, settings.MAILCHIMP_KEY)<span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			></span>

It seemed like the easiest way to only write the login once.

Finally, I had to create a few methods in the Model in question (in my case, this is my teacher model, as my users are called ‘Teachers’ in this bit.

def mailchimp_add_teacher_to_list(self, listname):
    """ Takes a listname, checks that the teacher is not a member of the list, then adds it. """
    client = mailchimp_get()
    listid = settings.MAILCHIMP_LISTS[listname]
    if not self.mailchimp_teacher_in_list(listname):
        data = {
            'email_address': self.user.email,
            'status': 'subscribed',
            'merge_fields': {
                'FNAME': self.user.first_name
            }
        }
        client.lists.members.create(listid, data)

def mailchimp_lists_get(self):
    """ TEMPORARY - Returns a list of all mailchimp lists """
    client = mailchimp_get()
    return client.lists.all(get_all=True, fields="lists.name,lists.id")

def mailchimp_teacher_in_list(self, listname):
    """ Returns a bool indicating if this teacher's email address is in the list """
    email = self.user.email
    client = mailchimp_get()
    results = client.lists.members.all(settings.MAILCHIMP_LISTS[listname], get_all=True, fields="members.email_address")
    members = results['members']
    addresses = []
    for m in members:
        addresses.append(m['email_address'])

    return email in addresses

I think the names should be pretty self-explanatory. The mailchimp_lists_get() method was just an experiment based on following the instructions in the documents.

Lastly, I created a view and a URL just to test these functions by printing to the console and looking at the (currently empty) lists in mailchimp.

Summary

It was my first time sitting down and thinking critically about what I wanted and how to do it and I have to say that mailchimp and the library basically made it painless. I have other project ideas that will require more API integration, and it’s made me hopeful.

Think Differently

Here’s a little thing you don’t know about me: I’m tired of hearing about Steve Jobs. I don’t know why, because I like stories from Elon Musk and his drive, but felt like the takeaway I got from the Steve Jobs biography was that people took it as permission to treat others poorly.

I say all that, because Steve Job is the focus of this chapter of The Obstacle is the Way. Better than Steve Jobs, though, is this quote that opens the chapter:

Genius is the ability to put into effect what is in your mind. There is no other definition of it.

-F. Scott Fitzgerald

I think that’s true. It’s what motivates me in my learning: finding the ability to make real (in some sense) the things I’ve only experienced in my mind.

The Steve Jobs part of the story can be summed up in these two paragraphs:

Steve Jobs was famous for what observers called his “reality distortion field.” Part motivational tactic, part sheer drive and ambition, this field made him notoriously dismissive of phrases such as “it can’t be done” or “we need more time.”

Having learned early in life that reality was falsely hemmed in by rules and compromises that people had been taught as children, Jobs had a much more aggressive idea of what was or wasn’t possible. To him, when you factored in vision and work ethic, much of life was malleable.

That seems to be the gist of the whole chapter: that a lot of our limitations are based on us having learned from an early age to be moderate in our expectations of ourselves and others. The lesson seems to be that we need to re-evaluate what we’re capable of and what we can expect from others.

Perhaps this will be the post that prevents me from ever being hired by “the next Facebook,” because I am not enamored of the “work seventy hours per week” startup lifestyle, and I believe in pushing yourself… but not in abusing yourself.

There is a story in the chapter about Steve Jobs telling his engineers that they couldn’t have an extra week to get something done… and the engineers eventually getting the project done within the initial time frame. And it’s framed as this great thing that Steve Jobs did.

However, I hear that and I think “those poor people’s families.” How much time at home did they miss? What are the chances that they were able to maintain whatever habits they had to keep their health and wellness up? What are the odds that any of them were the primary caregivers for their children? When their older, will they look back and think that moving a product a week earlier was worth the sacrifices they had to make?

I don’t know the answer to any of those questions, but I have a strong intuition…

So, in closing, this is from the next-to-last paragraph of the chapter, the same lesson stripped of the glorification of self-sacrifice:

An entrepreneur is someone with faith in their ability to make something where there was nothing before. To them, the idea that no one has ever done this or that is a good thing.

Burpees

Yesterday, I did something that I’ve been talking (to myself) about doing for a while: I added exercises to my run. Six times in my usual 7km run, I stopped and did 5 burpees.

burpees1

I don’t know why I picked them over any other exercise, except that they have the reputation of being super hard, and I was ready to have my butt kicked. Even more, I was ready to push myself into being seen being different. And they’re certainly different.

How was it?

First, let me say that I might have forgotten about them, except that I certainly feel the workout still. And I kinda like that.

Next, in addition to the fact that, although I felt self-conscious for the last set, my shyness decreased with each set, I’d like to say that I really enjoyed getting my hands dirty. It’s a funny thing to say, but for such a (self-perceived) nature-loving, Earth embracing hippy, I don’t get dirty very often. And, doing the burpees, I had to… and I liked it.

The last thing I wanted to mention as I reflect on them is that it was a fun change to start seeing the run as the ‘recovery’ part of the workout. I mean, after just five of them, I was so out of breath that I was glad to be running again. And that’s not how I usually thing about running.

When will I do them again?

My new short-term goal is to add a fourth, short run to my running week and to try and get the thirty burpees in just four sets…

If I do or don’t, I have to say that I’m feeling more active now, and I’m enjoying that level of activity.

Live in the present moment

There is not a lot to explain about this chapter title in The Obstacle is the Way. So, I’ll jump to the first quote that jumped out at me further on in the chapter:

For all species other than us humans, things just are what they are. Our problem is that we’re always trying to figure out what things mean–why things are the way they are.

It’s true, and it’s something I think about often. I mean, I tell myself that a deer in the forest isn’t thinking about the looming Monday and returning to work… it’s just feeling safe or unsafe. (To be fair, the deer doesn’t have to go to work on Monday.  But also, its chances of dying of old age are worse than mine.)

The basic idea, the way I read this chapter, is to say that we shouldn’t have a programmed future, as that gives us something to measure ourselves against. Are we progressing towards that future? Is this moment the way we told ourselves it would be?

The book doesn’t say this, but I assume that there’s no indication that we shouldn’t make plans, only that we shouldn’t let those plans overwhelm us.

Something I like about this book is that the author, Ryan Holiday, makes some concrete suggestions:

You’ll find the method that works best for you, but there are many thigns that can pul you into the present moment: Strenuous exercise. Unplugging. A walk in the park. Meditation. Getting a dog–they’re a constant reminder of how pleasant the present is.

And, he goes on to provide one more great piece of advice:

On thing is certain. It’s not simply a matter of saying: Oh, I’ll live in the present. You have to work at it. Catch your mind when it wanders. Don’t let it get away from you.

When it’s not easy for me, it’s good to know that it’s not easy for anyone.

Fitness in January

So, I don’t feel especially pushed to evaluate how my December training plan went, as I didn’t really make a detailed plan.

I was right that December is a hard time to focus on fitness and came away with these takeaways:

  • Trying for three runs per week was a good idea. I wound up very willing to compromise on the nature or quality of the run (shorter than planned? the day after a run day? No problem) and managed to get at least two runs in each week. Some, I even got in three including a few thirteen-kilometer runs.
  • There’s not really a point in hiding your fitness routine. I tend to hide the fact that I exercise. Nobody likes the fitness guy, right? So, I’ll talk about it only generally. And, during the first part of our hosting family, I didn’t get any exercise at all in (except some walking as we showed off the city). Then, after telling them that I do planks and that it helps with my back pain, it became easier to exercise in front of them.
  • I want to focus on abilities. It sounds weird, but nobody cares about reps. I say this because I can do a grand total of zero pull-ups. And, I could make a list of progressive goals for pull-ups, but that’s not what I get excited about. Instead, I’m still working on pull-ups, partly to do any (an ability) and as a stepping-stone towards tree-climbing and, possibly, bouldering.

The January Plan

Here’s what I’m looking at as I think about January:

First, I’ll be taking my son and a friend to a trampoline hall that has ‘ninja obstacle courses’ (I guess similar to American Ninja Warrior) and I look forward to measuring myself on those. (Also, to possibly turning two boys into workout partners.) She doesn’t know it yet, but because she’s feeling left out, my daughter will probably be taken bouldering with me this month as well. Another test of my general fitness.

To that end, here are the routines I’d like to have:

  • Running three times a week. Again, I’ll settle for the regularity now, and focus on the quality of the runs later.
  • Continuing the planks. I don’t get them done every day, but I think I can say I get them done two-thirds of the time and that they really help my back, as well as my overall feeling of strength.
  • More upper-body stuff. I have a sort of informal pull-up workout in my to-do list, and I get them done most of the time. To be honest, I’ve toyed with the idea of adding burpees to my run, partly for the workout and partly to force myself to accept looking weird in front of other people. Can’t hurt, can it?

Lastly, I think it’s good to have a goal to work towards, so there will be a 5k run for time at the end of the month.