Dorthy.com Blog

Starting Up In New York City

Posted: Feb 17, 2010 at 12:16 pm by Sarah Doody

nyc_skyline

Last month, Fast Company ran a story about why you should start a company in New York. They interviewed Fred Wilson of New York based Union Square Ventures to get an interesting perspective on the benefits and opportunities in New York as opposed to other areas such as Silicon Valley or Boston. A key theme of the article was that New York has a great mix of industries and individuals who have reached a maturity where they can lift and support each other through the process of developing a company.

As I read this article, I could not help being reminded about the story of how we chose New York as the city where we would start Dorthy.com …

In June of 2007, I had dinner with Jordan in Portland, Oregon and he was telling me all about this idea for a company. The big unknown was deciding where to base the company. When he mentioned New York City as a possible location, I remember nearly yelling, “Jordan, why wouldn’t the company be in New York?!?!”.

Having only visited New York City once for a quick weekend wedding years ago, I’m not sure why I was so convinced that New York was the place to start Dorthy.com … especially since he hadn’t talked to me about being a part of the team yet! Looking back, I guess it was because I associated New York City with people who really follow their passions, understand what it means to work hard, and do whatever it takes to make their ideas a reality.

New York really has the perfect blend of experience and explorers, maturity and mavericks, intelligence and innocence. The city and more importantly the people have provided the perfect stage for Dorthy.com. After being here for a little over 2 years, I could not imagine creating Dorthy.com anywhere else – doing what we love – in a city that is so captivating, curious, and creative.

* Here’s a link to the full article in Fast Company.

PS - Currently playing as I write this, “In New York … Concrete jungle where dreams are made of, There’s nothing you can’t do …” :)

 
 

Dorthy’s Tech team experiments with Twisted and Redis for Dorthy.com URL shortening service

Posted: Feb 10, 2010 at 12:31 am by admin

A few months ago the Tech Team at dorthy.com was tasked with the creation of an in-house url shortening service which will enable users to share dorthy urls over services like twitter.

We settled quickly on two technologies that would allow for rapid development and impressive performance.

Redis was chosen for persistence. It is an extremely fast data structures store and provides for simple replication and scaling on top of a clean programatic interface. We chose Twisted as our server framework as it’s simple event-driven networking architecture utilizing the deferred paradigm lends itself to rapid development and excellent performance for short-duration, non-computationally intensive tasks.

In this example we will illustrate how to create a simple protocol that allows requests for url setting and saving to be sent over the wire in JSON format. For a more robust system one may chose a remote protocol such as Google’s Protocol Buffers or the Apache project’s Thrift protocol which is well supported in the Twisted framework.

Setting up a basic twisted server is beyond the scope of this tutorial however the entire project can be downloaded here.

Encoding and Decoding functions

First lets take a look at the core functions of the system, which will be to create a “tiny” url like “http://dorthy.com/a/2Xg” from a “big” url like “http://www.dorthy.com/discover/h22f1/go-skiing-in-park-city-utah“. We would like the system to work with whatever base “tiny” url we’d like so we really only care about the last few digits of the tiny url, in this case “2Xg”. We’d also like to generate as many of these urls using the least number of actual characters possible. To do this we’ll start a numbering system that uses all of the digits 0-9 inclusive as well as all possible upper and lowercase characters; these are all things that should be fairly easy to type on all kinds of devices. When we sum those up and count them we get 62 available characters. We could store those “tiny” characters in redis as keys and use the big url as values, and keep track of the next key to be allocated in the server in memory. What if we want to one day expand the number of url shortening servers we deploy, but have them able to allocate new tiny urls independently? In this case we will choose to use redis’s incr function to allocate new numbers on the server side. This will ensure that all clients get a unique, one-time-use key. Redis’s incr function will take a given key and increase it’s value by 1 each time it is called and return the results. We will use a couple of functions in the included base62.py file to convert our “tiny” urls to and from integers. NOTE: the GYLPHS variable is our list of 62 characters we will be using for our tiny urls.

def b62enc(number):
    try:
        number = int(number)
    except ValueError:
        return -1
    if number < 0:
        return -1
    def tobase(remain, result=):
        """Recursive function to encode"""
        if remain == 0:
            return result
        else: return tobase(remain/BASE,
                GLYPHS[remain%BASE] + result)
    return tobase(number)

def b62dec(decodeme):
    decodeme = str(decodeme)
    if not decodeme.isalnum():
        return -1
    power = 0
    result = 0
    for letter in decodeme[::-1]:
        number = GLYPHS.index(letter)
        result += number*(BASE**power)
        power = power + 1
    return result

Setting up our Protocol - Subclassing Twisted’s base Protocol

We’d like to set up a server now, to listen on the wire for some JSON encoded requests for getting and setting shortened urls and fire back responses. In this example we’ll simply subclass twisted.internet.protocol.Protocol and define our own handlers for some functions. The core functions will be detailed below and a few others can be seen in the example file.

When our server receives some data, the dataRecieved function in our class will be called with the data as the parameter. We will decode that data and return an error if the data is incorrectly formatted or contains an invalid command. In the event the request looks solid, we’ll pass it on to a handler. This code is below.

    def dataReceived(self, data):
        """Main handler of incoming data"""
        try:
            message = jdecode(data)
        except ValueError:
            self.transport.write(jencode(ERROR_MSG))
            self.transport.loseConnection()
        if message['request'].lower() not in COMMANDS:
            self.transport.write(jencode(ERROR_MSG))
            self.transport.loseConnection()
        if message['request'].lower() == ‘get’:
            self.getHandler(message['url'])
        if message['request'].lower() == ’set’:
            self.setHandler(message['url'])

Connecting to and interacting with Redis in a Twisted Environment

This is where the magic starts. The handler functions are wrapped in the @defer.inlineCallbacks decorator. This wrapper, along with the txredis client library, is what allows us to do blocking network functions within an event driven environment like twisted without having to spawn another thread. These functions create a redis client, connect the client to the server, and issue commands using a generator-like syntax. After receiving results from their redis actions they’ll add their data to a “pre-fab” response object and send it along to the client

    @defer.inlineCallbacks
    def setHandler(self, url):
        """Handles a request by creating a b62 string for a url
            for a given b62 encoded string"""

        clientCreator = protocol.ClientCreator(reactor, Redis, **REDIS_CONFIG)
        redis = yield clientCreator.connectTCP(REDIS_HOST, REDIS_PORT)
        newkey = yield redis.incr(REDIS_INDEX)
        res = yield redis.set(newkey, url)
        ret = OK_MSG
        ret['command'] = ’set’
        ret['tiny'] = b62enc(newkey)
        ret['big'] = url
        self.sendIt(jencode(ret))
    
    @defer.inlineCallbacks
    def getHandler(self, url):
        """Handles a request by getting a url
            for a given b62 encoded string"""

        key = b62dec(url)
        if key < 0:
            sendIt(jencode(ERROR_MSG))
            return
        clientCreator = protocol.ClientCreator(reactor, Redis, **REDIS_CONFIG)
        redis = yield clientCreator.connectTCP(REDIS_HOST, REDIS_PORT)
        url = yield redis.get(key)
        ret = OK_MSG
        ret['command'] = ‘get’
        ret['tiny'] = key
        ret['big'] = url
        self.sendIt(jencode(ret))

The rest of the wiring to expose these functions to the network and do some logging can be seen in the source files provided with this tutorial. To run the server, make sure you have the required libraries (twisted, simplejson, txredis), and a redis server running on it’s default port and simply execute the shorterurl.py file in python. You can test out your server using telnet as follows:


$ telnet 127.0.0.1 5757
Trying 127.0.0.1…
Connected to localhost.
Escape character is ‘^]’.

{”request”: “set”, “url”: “http://www.dorthy.com/discover/h22f1/go-skiing-in-park-city-utah“}
<— you send this

{”big”: “http://www.dorthy.com/discover/h22f1/go-skiing-in-park-city-utah”,
“command”: “set”, “tiny”: “2Xg“, “respose”: “ok”}
<– you get this

$ telnet 127.0.0.1 5757
Trying 127.0.0.1…
Connected to localhost.
Escape character is ‘^]’.

{”request”: “get”, “url”: “3″}
<— you send this

{”big”: “http://www.dorthy.com/discover/h22f1/go-skiing-in-park-city-utah“,
“command”: “get”, “tiny”: 2Xg, “respose”: “ok”}
<– you get this

That is it for this tutorial but the dorthy.com Tech team would like to send much thanks out to the folks at contributing to Twisted, Antirez and the rest of the Redis contributors, as well as Dorian Raymer for the txredis libraries.

 
 

Social Media Week NYC

Posted: Feb 9, 2010 at 10:35 pm by Sarah Doody

Last week was Social Media Week and we had a great time getting to know some new people in New York.

On Tuesday, I went to Digital Divas at the Hotel on Rivington. Admittedly, I had three tickets to the event and for some reason, had the impression that it was for women only – oops! So I told the guys in the office that they couldn’t come (sorry guys – I’ll make up for it!)

Anyway, it was a great event. I always tell my friends who don’t live in New York that the city is much smaller than you think … and of course, one of the first people I ran into was someone I met at the #140conf meet-up in January. I also met people doing cool things in branded content and mobile technology.

Our Community Manager, spent most of Social Media Week at the Roger Smith Hotel, attending SUXORZ on Wednesday evening, where she voted on some of the worst social media campaigns of 2009 (see: RyanAir, TimeWarnerUnCares, Twitter billboard epic fail) and attended a social media lunch with 50 other members of the #140conf community to discuss the state of now media.

A few members of the Dorthy.com team beat the crowds at Obliterati where we met some new friends in New York’s media and technoogy scene. Thanks to R Bar for hosting the great event - and drinks!!

On the calendar for the rest of the month, here are the events I’m planning on checking out, would be lovely to meet up if you’re going to any.

- Hive at 55 Happy Hour (February 10)

- NYC Web Grrls (February 10)

- She Says

- #140conf meet up (February 23)

- Creative Morning (February 24)

Let us know of any events that you think might be interesting for us to go to. We’re always up for meeting new people and talking about ideas.

 
 

A review of Dorthy.com “my new favorite”

Posted: Jan 29, 2010 at 06:14 pm by Sarah Doody

Hey this is Sarah. I’m the Director of Product Development here at Dorthy.com. I love hearing what you think about Dorthy.com … it really helps keep me focused on what you love about Dorthy.com and also helps me figure out what we can do to make Dorthy.com more useful for you :)

This morning, I found a blog that made me smile. One of our users wrote a review and said that Dorthy.com “just might be my new favorite” … thanks Amy!

Here’s a little bit of her review:

“You complete a sentence ‘I want to…’ and up pops your dreampage with articles, videos, photos, and blog posts that it collects from all over the web …. On the same page, you can create a custom plan of action by notes, saved items, etc.

I just created 3 to experiment and I’m already hooked. YOU WOULD NOT BELIEVE how many great links, photos, and videos popped up …”

Head over to Amy’s blog to read her full review.

Be sure to let us know what you think of Dorthy.com by sending us your thoughts on our feedback tool or by leaving a comment on our blog.

PS - You can also reach out us on Twitter: @dorthy or @sarahdoody

 
 

If at first you don’t succeed …. fix it :)

Posted: Jan 29, 2010 at 06:13 pm by Sarah Doody

Ok, have a confession – the community section of each dreampage was not working as planned. When you chose to “Subscribe” to another person’s dreampage, we were only showing you the Activity starting at the day that you subscribed to them. But, really, it was supposed to be showing you their activity from the very first day the page was created. The good news – it’s working correctly now.

The idea is that it if you want to Go skiing in Park City Utah and you subscribe to someone else’s dream about skiing in Utah, you could probably learn a lot from seeing what they’ve done – what content they’ve viewed or saved and things like Notes or Plans that they’ve created.

Check out this example in action: Activity for Go skiing Park City Utah.

Now, the Activity is much more helpful for you because it shows what others are doing around your interest.

Let us know what you think about the changes. We would love your feedback on this.

 
 

Save the stuff you like so you don’t have to search for it again

Posted: Jan 29, 2010 at 03:05 pm by admin

How many times have you found something cool, but a few days later, forgotten where you saw it? It frustrates us too! Traditional bookmarks work for a while, but then, things get disorganized quickly.

On Dorthy.com you can save any piece of content, and it goes into your Saved Stuff for that specific dreampage.

Let’s say you have a page to Learn To Ski, and you see a cool video on Dorthy.com about someone taking ski lessons, or maybe an article reviewing a local ski school. With Dorthy.com, you could save the article or video, and then it would be within your Saved Stuff for your Learn To Ski page. So, we help you keep everything organized around your interest – and not mixed up with other things you’re interested in.

dorthy_actions_savedstuff

 
 

Introducing Topical Twitter Discussions

Posted: Jan 25, 2010 at 03:49 pm by Jordan English Gross

We like Twitter and there’s a lot of smart people on there. So, we decided to add a Twitter section to each of your individual dreampages.

On the Twitter section, we’re always doing a live search for tweets that relate to your page. So, if your page is to Lose 20 Pounds we would find tweets for you that relate to losing weight. We’ve also built in the ability for you to reply to tweets and send tweets directly from your page on Dorthy.com – so you can engage in conversations and learn from others.

We hope that the idea of our topical Twitter discussions will help bring you more relevant information about anything you want to do – and connect you with people who know about it.

dorthy_twitterlistfull

 
 

Tweet your latest discovery

Posted: Jan 24, 2010 at 01:42 pm by Sarah Doody

We know many of you are on Twitter. So, we’ve made it easier for you to tweet about your interests and stuff you find interesting on Dorthy.com. On our Twitter page, we’ve included a way for you to post tweets without ever leaving Dorthy.com.

To start using this feature and tweet about your interests, you need to connect your Twitter account - which you can do via your Settings page.
That’s only part of the story though. We’ve also included a way to see live Twitter searches and topical Twitter discussions that relate to what you’re interested in.

dorthy_tweetsentfromdorthy

 
 

Invite other people who want to learn about or achieve the same things as you

Posted: Jan 23, 2010 at 06:30 pm by Sarah Doody

Want to invite your friends to join you on Dorthy.com? Now that we’ve lifted our wait list – anyone can join. So what are you waiting for?

If you are logged in, go to the Invite Friends page. From here, you can choose to enter the email addresses of the people you want to invite, or you can import your contacts from your address book on sites like Gmail, Hotmail, or Yahoo Mail.

We’re guessing that you and your friends have some common things that you want to learn about or achieve. Maybe you and your friends want to plan a trip, do a sport, or learn something new. Whatever you want to do, its better to do it together. So Invite Your Friends to join you on Dorthy.com.

dorthy_invitefriends

 
 

Technorati calls Dorthy.com your new search BFF

Posted: Jan 19, 2010 at 07:06 pm by Jordan English Gross

Leslie Grandy mentions that users today are looking for “referrals from taste-makers, analysts, and friends to help discover what is called “the long tail” of content”, and that you could have a new search BFF in Dorthy.

“Dorthy is like a cocktail party host, making social introductions to new people and interesting things”.  The original article is titled “Beyond Bing, Does Semantic Search Work?” and can be read here.