Burrito Wednesday #5: Tomatillo at The Big Hunt

Posted: July 5th, 2010 | Author: | Filed under: Burrito | Tags: , | No Comments »

That's no moon bar, it's a space burrito station!

Burrito Wednesday #5 — Tomatillo Taqueria at The Big Hunt.

This was a suggestion from Marian and her coworker, and I’m very glad I listened. Thanks, ladies! It’s a bit of hike from the office, but I think it ended up being worth the trip.

During the day the big hunt rents the window of their bar out to these guys to sell burritos and taco. There’s no seating or anything, just a big open window at counter height. Two guys in there pumping out tasty, comparatively authentic seeming dishes. They branded it pretty well, with signs and menus and such. It didn’t seem nearly as odd as I expected, which was nice. They get bonus points for simple pricing, and it looked like the tacos came in more traditional corn tortillas – awesome.

The veggie burrito was solid – rice, black beans, some sort of stewed green peppers & onions, and guacamole. I added salsa fresca, tomatillo salsa, lettuce and cheese. The cheese was nice, perhaps Panela but maybe something else. They turned them out pretty quickly, and it came to $6.

Building my delicious, tasty burrito.

The burrito looked tasty, but wasn’t especially hot. There was no seating there, and I incorrectly decided to walk back to the office instead of going to the park. By the time I got back to the office with my burrito it was merely lukewarm. I dug in and it was tasty, but overall the luke-warmness was a big let down. All my fault, but sad none the less. I’ll have to go back and eat one straight away.

Here we go, nom nom nom.

I was digging in and enjoying it so much I nearly forgot to take a picture, that’s the only one I got. Mmmm. The ingredients were well distributed and nothing especially stood out for good or bad. It was well made and consistent. It was definitely on the smaller side, and probably much healthier than the others I’ve reviewed. However it made me wish I had a few chips and some salsa to go along with it.

I’d rate it a 3 on the arbitrary scale.

No Comments »

Burrito Wednesday #4: Casa Blanca

Posted: June 30th, 2010 | Author: | Filed under: Burrito | Tags: , | No Comments »

Casa Blanca. It's... unassuming

Burrito Wednesday Week #4: June 23, 2010 — Casa Blanca.

This wasn’t my prime option today, but unfortunately it was 2:30 and choices #1 and #2 were already closed. The weather was hot, and this has the advantage of being in the same building as me. I know a few people who love it, but the few times I’ve been it’s not been exceptional. It has a very… authentic kind of feel. They clearly aren’t interested in being a fancy restaurant – they just want to make food cheaply.

Unassuming? Slightly grody?

Swinging in at 2:30, it was fairly empty. There was a world cup game on the TV, and most of the folks were watching it. They were slow to take my order because they were counting money or something. Eventually they got my veggie burrito. I’m fairly sure I got a dinner entree, but not 100%. I don’t recall the exact price, but it was a bit more expensive. The standard veggie came in a styrofoam tray with fresh salsa, rice & beans on the side, and a nice green hot sauce. Inside the burrito we had more beans, some onions, cheese, some lettuce. Nothing too exciting. To make this sing you really had to mix the rice, salsa hot sauce and burrito all together. As a result the extra beans on the side were pretty unnecessary.

Tasty, messy burrito

It was huge, which is nice. The salsa was good, beans pretty good. It remained pretty interesting for most of the eating, which was an accomplishment considering the size. I had very, very low expectations based on some past experiences, but this definitely exceeded it. Might be worth coming back for a happy hour negra modelo on a pleasant afternoon.

I’d rate it a 2 on my arbitrary scale. Pretty good, but not mind blowing. The salsa and hot sauce really saved the day.

No Comments »

Burrito Wednesday #3: Burrito & Coffee Cart

Posted: June 16th, 2010 | Author: | Filed under: Burrito | Tags: , | 1 Comment »

The Burrito & Coffee Cart at 17th and K

Burrito Wednesday Week #3: June 16, 2010 — The Burrito and Coffee Cart.

A mere two blocks away from from Pedro & Vinny’s cart is another burrito cart. Back in 2004 I’d occasionally grab a latte here on the way into the office. I got a burrito once or twice, and was pretty disappointed. Since then I’ve stuck with Pedro & Vinny. However, for the cause of Burrito Wednesdays we must push outside of our comfort zones.

Carlos isn’t as personable or friendly as John. The ordering was much more difficult – he made assumptions and didn’t really ask what exactly I wanted. I ended up with, basically – spinach tortilla, rice, black beans, cheese, a bit of boring salsa, guac and some Cholula. It was something around $6.

Burrito under construction

Unfortunately it wasn’t very good. The tortilla was fine. The cheese was very nicely melted and it was well distributed throughout. The guacamole was definitely the highlight, but it was just from a cosco tub. Frankly, I was hoping from something a bit more unique. The beans and rice were just terribly bland and boring. I didn’t particularly want to finish it, not because of volume but because it was boring. I really can’t see coming back when the fundamental ingredients don’t hold any interest. I give some credit that it was very tidy – unfortunately it was too tidy. Too buttoned up. Too blah.

Sadly it doesn’t score better than 1 on the arbitrary & meaningless scale.

Burrito under consumption

1 Comment »

Burrito Wednesday #2: June 9th – Pedro & Vinny’s cart

Posted: June 9th, 2010 | Author: | Filed under: Burrito | Tags: , | No Comments »

Pedro and Vinny's burrito cart on K St

Burrito Wednesday Week #2: June 9, 2010 — Pedro and Vinny’s Burrito Cart. (Warning, that’s one of the most obnoxious websites ever).

This is one of my more frequent burrito sources. It’s a block from my office, vegetarian and delicious. Styling little cart at 15th and K Sts with a generally long line. Plus, check out the awesome new sticker on the side. The key here is the fantastic selection of hot sauces. He has 3 homemade ones – the infamous classic mango habanero, a tasty cilantro and a new spicy brown sauce I believe he’s calling “K Street Habanero.”

John Rider at work making a burrito, surrounded by the sauces.

There’s a whole system here. While in the (usually long) line you’ll give John your tortilla choice and yes/no to cheese – I go for tomato chili cheese. While you wait in line the tortilla steams and the cheese melts.

When you get up to the cart there’s a flurry of options to determine your burrito. My choice is usually medium (warning: small has no rice), black & tan (meaning both black beans and refried pinto beans), fresh salsa, guac, and various hot sauces. Usually the mango plus something else to make it hotter. Lately that’s been the “triple delight,” all three of his homemade sauces.

Burrito construction near completion

The total winds up at $6.50 for mine. Cash only and you make your own change. How’s it taste? Fantastic. The rice can be a little dry on occasion, and the beans can be a little bland. However when it’s loaded with good sauces, guac, etc it’s really quite flavorful and satisfying. My biggest complaint consumption side would be that it’s very messy to start and end. Take a look at when I pealed off the first part of foil.

Peeling back that first foil, it's mess as all get out. But it's going to be delicious!

However once the main burrito section is average messiness for a burrito. I feel like in the past (particularly pre-hiatus, he spent almost a year down in the Carolinas or Georgia possibly setting up a storefront down there, but came back) they were a bit more controlled and less messy. Regardless, it was tasty. You even get a free York peppermint patty at the end! I think these get a solid 4 on the arbitrary & meaningless scale.

Burrito consumed. Foil and paper towel carnage everywhere, and the peppermint patty steps up to bat.

No Comments »

Burrito Wednesday #1: Chipotle Dupont

Posted: June 2nd, 2010 | Author: | Filed under: Burrito | Tags: , , , | No Comments »

I’ve decided that the time has arrived for the establishment of a new tradition in our great lands: Burrito Wednesday. Everyone agrees that burritos are a delicious and amazing food.

What, wait, why? The concept is delightful in its simplicity. Every Wednesday you should go out in search of a new burrito to try. Ideally these would be entirely new locations, but for my purpose I’m going with a “no repeats” model, where places I’ve been too before are fine, as long as it hasn’t been the featured Burrito Wednesday candidate. Why Wednesday? For one, it’s a shitty day of the week and a nice burrito institution would liven it up. For another, I don’t have any standing meetings around lunch time on Wednesday, like I do on most of the other days of the week.

Please join me (either in a literal, have a burrito at the same table sense or metaphorically) in this new tradition. If Wednesday is bad for you, heck, make it Burrito Monday. Why not? I’ll be maybe posting here about the burritos I consume

Week #1: June 2nd, 2010 Chipotle Dupont Circle

Chipotle Dupont Circle

I started off with a close, convenient location – Chipotle Dupont Circle. Yes, you might assume you’ve been to Chipotle and know all there is to know. However this branch has a surprise in store – it features the delicious vegan Garden Blend. A fake meat product, it’s quite tasty and rare. This is the pilot location for the stuff, so it’s not quite your regular Chipotle fare. Today I got a burrito with rice, peppers & onions, black beans, garden blend, salsa fresca, tomatilla hot sauce and cheese. I intended to toss corn & lettuce on there, but screwed up. The total came to $6.71 with tax.

The burrito itself was rather tasty. The lack of veggies was a bit of a disappointment, and the hot sauce wasn’t too exciting. The second half sorta dragged on, without much to keep me engaged. Overall it was big, and tasty. Without the garden blend I’m not sure I would have cared much, but the garden blend is unique and interesting. I highly recommend it. I’d rate it about 3 stars on my meaningless and uncalibrated scale.

Partial Burrito Love

In upcoming weeks I hope to feature all my regular burrito spots, and expand to some new ones. Pedro & Vinny’s, CalTort, The Well Dressed Burrito, Baja Fresh, Qdoba, Pica Taco, the 17th st cart and a bunch of others. However I’d love suggestions of places to try out that are within reasonable transit distance of Dupont Circle/Downtown DC. Happy burritoing.

No Comments »

pmxbot command: lunch!

Posted: May 14th, 2010 | Author: | Filed under: Nerdery | Tags: , | No Comments »

As everyone is well aware, lunch is the most important part of the work day. However it’s often hard to find inspiration when deciding on a delectable dining destination. The ideal solution is to have someone propose options, and everyone reject them until consensus is reached. However nobody enjoys that. Computers can propose options, but that’s less social.

pmxbot has an existing !lunch command that’s supposed to help. Unfortunately you have to fill out the dining list yourself, and frankly, that’s a pain. The result is lots of old, bad definitions in a few limited areas. It does let you sneak in some comedy options (What to have in Canton? PB&J? Leftovers?), but for the main purpose it kinda sucks.

The solution is to use someone else’s database. I cooked one up yesterday pretty quickly using Yahoo Local’s API and the pYsearch convenience module. The result is quite easy, really. The only wrinkle is you need that module (someone could rewrite it to use just urllib and simplejson, if they cared) and a Yahoo API key.

The code is below, also available at http://libpa.st/2K0kh.

@command("lunch", doc="Find a random neary restaurant for lunch using Yahoo Local. Defaults to 1 mile radius, but append Xmi to the end to change the radius.")
def lunch(client, event, channel, nick, rest):
        from yahoo.search.local import LocalSearch
        location = rest.strip()
        if location.endswith('mi'):
                radius, location = ''.join(reversed(location)).split(' ', 1)
                location = ''.join(reversed(location))
                radius = ''.join(reversed(radius))
                radius = float(radius.replace('mi', ''))
        else:
                radius = 1
        srch = LocalSearch(app_id=yahooid, category=96926236, results=20, query="lunch", location=location, radius=radius)
        res = srch.parse_results()
        max = res.totalResultsAvailable if res.totalResultsAvailable < 250 else 250
        num = random.randint(1, max) - 1
        if num < 19:
                choice = res.results[num]
        else:
                srch = LocalSearch(app_id=yahooid, category=96926236, results=20, query="lunch", location=location, start=num)
                res = srch.parse_results()
                choice = res.results[0]
        return '%s @ %s - %s' % (choice['Title'], choice['Address'], choice['Url'])
No Comments »

Facebook and Apple should both be scared.

Posted: May 13th, 2010 | Author: | Filed under: Philosophising | Tags: , , , | No Comments »

The ever clever DrJonboyG linked to this article about Facebook being too large to adequately handle dispute. Luckily I haven’t had to deal with that part of the service. However like all their users I’ve had to deal with them, and other services, viewing user privacy and security as a tertiary, at best, concern. It seems like over the last year or so we’ve entered what feels, to me, like a big slide back in individual user rights in technology.

In the mid-2000s everyone was in favor of openness. Big players had APIs, folks opened their systems up, open source was considered cool, mashups were all the rage. More recently, the biggest players took a look at that, and seemed to realize that they had most of the cards, and that they could turn this openness into a one way street. Facebook asked itself, “Why should we integrate with anyone else, when we can try to force everyone else to integrate with us?” They also looked around and realized they had a lot of information about people, information that was valuable to advertisers and others. If they combined steps 1 & steps 2 they could easily have more control, more relevance, more information, and therefore more money. Matt McKeon and The NY Times have excellent visualizations of Facebook’s evolving privacy policies.

Facebook is certainly pissing off a lot of users who’ve noticed this. Research from my employer suggests that it’s mostly the 35+ group that’s pissed off, but anecdotally I know many in their 20s that are angry about it. I have yet to see anyone defend the expansionist policies. I support the idea of reducing redundant and unnecessary logins, but Facebook as the one-true-account has never sat right with me. The issue for me isn’t any one thing right now – I (think I) turned off the privacy settings I object to, and prevent Apps from doing things I object to. However they’re destroying the goodwill I have toward them, and making it more like that I’d kill my account there and jump ship.

I view Apple’s policies with the iPhone as fairly similar. They’ve had a pretty good lead and an excellent product, but their continued asinine policies are destroying not just their market share, but the good will people feel to the brand. I actually don’t have that many objections to AT&T lately, but I know that’s a major sticking point for many. My objections are almost all related to openess and control. One of the major reasons I love OSX is that it gives me the best of both worlds – I have a polished UI with excellent commercial and free desktop software, as well as robust open source software and plenty of control. I can swap out a SSD, run server software, use Homebrew to easily install traditionally linux software. This combination is more than the sum of its parts, for me.

However Apple has done the opposite with the iPhone – making it more locked down and controlled than just about any other device I use regularly. I can’t install random software I want to. I can’t use it easily/cheaply in Europe. I can’t tether with it. I can’t customize the interface. I don’t want flash on my smartpone at all (and use click to flash on my laptop) but Apple’s sweeping rejection of non-Objective-C apps is a dangerous prescedent, and I am sad that whatever other cool stuff a developer might come up with may be stifled by the new policy. The new features in iPhone OS4 are hardly anything to get excited about – more ads, more obnoxious ads, extremely controlled multitasking for limited uses, and removing a few of the limitations on the private APIs.

Android has overtaken the iPhone in US sales, and anecdotally I know many people in the Smartphone market who’ve gone for Android devices like the HTC Incredible. I know that the 4th generation iPhone this summer will be a much harder sell to me, and many others. We’re tired of Apple incompetently managing their walled garden, and Google has cleverly provided the alternative. Developers who’ve been bit by AppStore policies may moving elsewhere.

Twitter has some potential trouble with their developer ecosystem. They now have official iPhone (Tweetie, which I use, bought and rebranded), Blackberry and Android apps, potentially alienating many of the third party developers already. They’ve basically stated that they’re going to be moving in to plug holes in the service that third parties are filling now. In the end, I think that’s good. It’s stupid to expect people to know about and use bit.ly, twitpic.com, etc. However they’re also increasing the risk of those developers fleeing to a competing service as well. The changes twitter is introducing are the least risky in my opinion – they’re codifying a lot of the stuff the ecosystem has built and making it easier for all users to do what many already do. I think there will still be room for innovative services (like bit.ly’s analytics) and clients (like CoTweet and TweetDeck providing business user features).

It’s interesting to see how these great tech companies who’ve built very successful products seem to be missing their achilles’ heels. They have big established market share, but refusal to deviate from their established plans seems to be costing them dearly in terms of consumer interest and good will. Facebook and Apple both had near monopolies in their sectors. They’re strong, good companies with lots of intriguing ideas. However they’re inflexible, and hard to deal with. I see big problems in both their futures unless they learn and change directions.

No Comments »

Library Paste

Posted: May 3rd, 2010 | Author: | Filed under: Nerdery | Tags: , , , | No Comments »

The ever impressive Jamie wrote a nice little paste bin at work a while back. It was dead simple to use, relatively private (in that it used UUIDs and didn’t have an index), and hooked into pmxbot. Unfortunately like most of the code written internally it used a proprietary web framework that’s not open source. It’s like cherrypy & cheetah, but different.

I decided to modify jamwt’s pastebin to make it open sourceable. It’s now up on BitBucket as Library Paste. It uses cherrypy with Routes (NB: Must use routes <1.12 due to #1010), mako for templating, simplejson plus flat files for a database, and pygments for syntax highlighting. One of the great features is that it also allows one click sharing of files, particularly images. How handy is that?

For code – you specify a Pygments lexer to use and it will highlight it with that when displayed. You can leave it unhighlighted, and always get the plain text original.

For files – it will take anything. It will read the mime type when you upload it, and set it on output. It will tell your browser to display it inline, but it will also set the filename correctly so if you save it you’ll get whatever it was uploaded with, rather than the ugly uuid with no file extension.

There are a few minor improvements from the in house original. First, the upload file is on the same page rather than separated from uploading code. Second, it handles file names with spaces better. Third, there is no third.

I’d really like to get configuration/deployment setup. What’s considered a good, flexible way to to make it easy for folks to deploy an app like this? Use cherrypy config files, build a little bin script and optionally let folks run it behind wsgi if they want to nginx/apache it?

I’d also like to try with putting it up on Google App Engine. Looks like you have to jump through a few hoops to adjust code to use it, and I’d have to adapt the flat file system to use their DB.

One nifty “hidden” feature it has is that you can ask it for the last UUID posting for a given user, if they filled in the nickname. You simple visit http://host/last/user and get back a plain text response with the UUID. pmxbot can use this to provide a link to someone’s most recent paste. Here’s the generic pmxbot function we used.

@command("paste", aliases=(), doc="Drop a link to your latest paste on paste")
def paste(client, event, channel, nick, rest):
    post_id = urllib.urlopen("http://paste./last/%s" % nick).read()
    if post_id:
        return 'http://paste/%s' % post_id
    else:
        return "hmm.. I didn't find a recent paste of yours, %s. Try http://paste to add one." % nick

Update:

I’ve since made a google app engine compatible version. It’s publicly hosted and you’re welcome to use it. http://librarypastebin.appspot.com and at http://libpa.st. Yes, I bought a stupid short URL for it!

No Comments »

Cherry Blossom Ten Miler

Posted: April 13th, 2010 | Author: | Filed under: personal | Tags: , | No Comments »

Last spring, at the end of April/beginning of May, I decided to start running. I did Couch To 5k using the excellent podcasts from Robert Ullreys. My first race ever was a 5k last fall, the College Park Cares 5k. I finished in 27:45 gun time, but the start was a mess so I was probably a bit faster. I really need to dig up the photos from the race, but darned if I can find them.

Fast forward to this Sunday when I ran my second race, the Cherry Blossom Ten Miler. This was a rather huge step up. I’ve had IT Band problems since the beginning of March, and didn’t run nearly enough during the winter (those two facts are certainly related). I was rather nervous about the race before hand. My Forerunner 305 was saying my HR was 121 just standing in the starting area, waiting. However, I finished! My knee was fine for most of the run, I had a little left to push that last mile, and did it in 1:47:15, or 10:44 per mile. Not particularly good, but I did it. I tracked it with the Forerunner, and shittier runkeeper.

Me crossing the finish line, finally! The image is from marathonfoto.com, which seems to be incredibly overpriced and poorly made.

I still don’t know if I actually enjoy the running, but it’s convenient. It’s fun at times, and I mostly enjoy being active. It’s flexible, I can do it in the city with very minimal equipment. No bike to store, etc. I also enjoy the goal of having a race to work toward and keep me focused, I’ll need to find another. I think I’m going to start doing more interval training, maybe 20 minutes with 5-10 cycles of sprinting, with jogging between. Mix in a longer run on the weekend and it seems like a reasonable approach.

No Comments »

Custom pmxbot actions

Posted: April 7th, 2010 | Author: | Filed under: Nerdery | Tags: , , | 3 Comments »

My employer just open sourced a fork of the IRC bot we’ve been using internally for years, pmxbot. jamwt and some others are responsible for all the good parts of it, but I’ve been responsible for most of the feature bloat for the past few years. The open source version strips out internal code that or didn’t need to be shared, and overall makes it much more flexible for others to use.

It’s really a pretty great system, and I’m going to share some of the actions that we didn’t release, but that you might get some value or inspiration from. Of note, a few of these will reference internal libraries, so you’ll need to switch ’em to use urllib2 or similar.

The basic way you extend pmxbot is with two decorators. The first is @command, and the second is @contains. @commands are commands you explicitly call with “!command” at the beginning of a line. @contains is a very simple pattern match – if the phrase you register is in the line (literally “name in lc_msg”).

When you use the decorators on a function you’re adding it to pmxbot’s handler_registry. Every line of chat it sees will then be checked to see if an appropriate action exists in the registry, and if so the function is called. It goes through the registry in a certain order – first commands, then aliases, then contains. Within each group it also sorts by descending length order – so if you have two contains – “rama lama ding dong” and “ram” – if a line had “rama lama ding dong” it would execute that one. pmxbot will execute exactly 0 or 1 actions for any line.

The decorators are fairly simple – @command(“google”, aliases=(‘g’,), doc=”Look a phrase up on google, new method”). First is the name of the command “google”, which you trigger by entering “!google.” Second is an optional iterator of aliases, in this case only one, “!g.” You could have several in here, such as aliases=(‘shiv’, ‘stab’, ‘shank’,). Last is an optional help/documentation string that will be displayed when someone does “!help google”. The contains decorator is the same, but uses @contains and doesn’t support aliases.

A command is called when it’s picked out of the handler registry to handle the action. Any handler will be called with the arguments – client, event, channel, nick and rest. You can ignore client and event for 99% of cases, they’re passed through from the underlying irc library. Channel is a string containing the channel the command was made in. Nick is the nickname of the person who made the call. Rest is the rest of the message, after the command prefix is removed if it’s a command. For example if we saw the following line in #pmxbot: “<chmullig> !g wikipedia irc bots” the google function would be called with channel == “#pmxbot”, nick == “chmullig” and rest == “wikipedia irc bots”.

A basic command

Putting it all together, let’s look at a basic command – !google.

@command("google", aliases=('g',), doc="Look a phrase up on google")
def google(client, event, channel, nick, rest):
	BASE_URL = 'http://ajax.googleapis.com/ajax/services/search/web?v=1.0&amp;'
	url = BASE_URL + urllib.urlencode({'q' : rest.strip()})
	raw_res = urllib.urlopen(url).read()
	results = json.loads(raw_res)
	hit1 = results['responseData']['results'][0]
	return ' - '.join((urllib.unquote(hit1['url']), hit1['titleNoFormatting']))

It registers the function google, under the command google, with an alias g. Note that the google function doesn’t have to match the name in the decorator, it can be anything. Within this function we can do anything you could want to do in python – we use urllib to call google’s ajax apis, and use simplejson to parse it and return the URL and title of the first hit. Anything returned or yielded from the function is passed back to the channel it was called from. If you want to have pmxbot perform an action, just return text that begins with “/me.”

Now let’s do a short contains example – simple enough.

@contains("sqlonrails")
def yay_sor(client, event, channel, nick, rest):
	karmaChange(botbase.logger.db, 'sql on rails', 1)
	return "Only 76,417 lines..."

This one has no doc (you can’t get help on contains ATM) and it’s pretty simple. That karmaChange line increases the karma of “sql on rails,” but we’re not talking about karma.

Yahoo

You’ll need the BOSS library for this, and you’ll need to register an API key and put a config file where the library expects it. However it works fine once you do all that.

@command("yahoo", aliases=('y',), doc="Look a phrase up on Yahoo!")
def yahoo(client, event, channel, nick, rest):
	from yos.boss import ysearch
	searchres = ysearch.search(rest.strip(), count=1)
	hit1 = searchres['ysearchresponse']['resultset_web'][0]
	return hit1['url']

Trac

This is one of my favorites. We use Trac internally for ticketing. We have two commands that use the XMLRPC plugin for Trac to make it accessible for pmxbot. The first finds any possible ticket number (eg #12345) and provides a link & ticket summary. Note that we put a hack into the handler registry to make this the first contains command it checks, you could do something similar if you wanted to modify it.

@contains('#', doc='Prints the ticket URL when you use #1234')
def ticket_link(client, event, channel, nick, rest):
	res = []
	matches = re.finditer(r'#(?P<ticket>\d{4,5})\b', rest)
	if matches:
		tracrpc = xmlrpclib.Server('https://user:pass@trac/xmlrpc')
	for match in matches:
		ticket = match.groupdict().get('ticket', None)
		if ticket:
			res.append('https://trac/ticket/%s' % ticket)
			try:
				res.append(tracrpc.ticket.get(int(ticket))[3]['summary'])
			except:
				pass
	if res:
		return ' '.join(res)

The second uses the RPC to search trac for a ticket or wikipage that might be relevant.

@command("tsearch", aliases=('tracsearch',), doc="Search trac for something")
def tsearch(client, event, channel, nick, rest):
	rest = rest.strip()
	url = 'https://trac/search?' + urllib.urlencode({'q' : rest})
	tracrpc = xmlrpclib.Server('https://user:pass@trac/xmlrpc')
	searchres = tracrpc.search.performSearch(rest)
	return '%s |Results: %s' % (url, ' | '.join(['%s %s' % (x[0], plaintext(x[1])) for x in searchres[:2]]))

Notify

This one is a total hack, but we were having issues with coordinating a certain team. We added a !notify command to help folks easily let everyone, online & off, know what they were up to. It simple sent an email to a distribution list.

@command("notify", doc="Send an email to list@domain.com, let them know you accidentally wiped a server.")
def notify(client, event, channel, nick, rest):
	server = smtplib.SMTP('mail.domain.com')
	notification = '%s: %s' % (nick, rest.strip())
	try:
		sigraw = rand_bot(client, event, '!notify', nick, rest)
		if type(sigraw) == GeneratorType:
			sigraw = '\r\n'.join(sigraw)
		signature = '\r\n\r\n--\r\n%s' % sigraw
	except:
		signature = ''
	msg = 'From: pmxbot@domain.com \r\n'\
		'Reply-To: list@domain.com \r\n'\
		'To: list@domain.com \r\n'\
		'Subject: !notify: %s \r\n\r\n'\
		'%s \r\n\r\n'\
		'Hugs & Kisses,\r\npmxbot'\
		'%s\r\n\r\n' % (notification, notification, signature)
	server.sendmail('pmxbot@domain.com', ['list@domain.com',], msg)
	server.quit()

Invite

This one is a little weird, but as more people got on IRC we wanted to send them a little email to let them know how to access it, etc. It’s also useful to harass people who aren’t online, but should be.

@command("invite", aliases=('spam',), doc="Send an email to an invitee, asking them to join irc.")
def invite(client, event, channel, nick, rest):
	server = smtplib.SMTP('mail.domain.com')
	if rest:
		try:
			inviteText = rest.split(' ', 1)[1]
		except:
			inviteText = ''
		invitee = rest.split(' ', 1)[0] + '@domain.com'
		try:
			sigraw = rand_bot(client, event, '!notify', nick, rest)
			if type(sigraw) == GeneratorType:
				sigraw = '\r\n'.join(sigraw)
			signature = '\r\n\r\n--\r\n%s' % sigraw
		except:
			signature = ''
		msg = 'From: pmxbot@domain.com \r\n'\
			'Reply-To: noreply@domain.com \r\n'\
			'To: %s \r\n'\
			'Subject: join us in irc! \r\n\r\n'\
			'%s \r\nRemember, you can find about irc here: https://intranet/IRC\r\n'\
			'You can access IRC via your web browser at https://domain.com/irc \r\n\r\n'\
			'Hugs & Kisses,\r\n%s & pmxbot'\
			'%s\r\n\r\n' % (invitee, inviteText, nick, signature)
		server.sendmail('pmxbot@domain.com', [invitee,], msg)
		server.quit()

Personal Responses

We have a ton of these, this is just one example. They watch for people being referenced, and occasionally (the randomness is key for many of them, to keep from being obnoxious) respond.

@contains("elarson")
def elarsonthemachine(client, event, channel, nick, rest):
	if nick == 'elarson' and 'http://' not in rest and 'https://' not in rest:
		return 'elarson - The Machine!!!'

Other RPCs

I won’t show you the code, because removing the specific stuff would make it boring. But we have about a half dozen internal RPCs we can call with it. Some use Pyro, others XMLRPC. That trac search example is pretty representative.

RSS/Atom

We have pmxbot monitoring about a half dozen RSS feeds. The intranet and dev site both have them, we monitor twitter search for a bunch of keywords, as well as google news. It’s a pretty sweet feature, if you ask me.

In conclusion, pmxbot is awesome. I’d like to make it even easier for people to add their own features. Maybe include a setting in the YAML conf file that’s a python file which is imported? What else do you have (all zero of you using pmxbot)?

3 Comments »