The spammers are getting more creative. Just got this from Teresa Albert (teresa.albert503@yahoo.com)…
With due respect and humility am writing you. Though i know this email will come to you as a surprise and i simply ask that you follow your heart before you respond to what i am about to say.
I have been informed by my Oncologist that I would not Last for the next two week due to an internal illness that has been going on for seven years. I have been down with Ovarian Cancer but what bothers me is my stroke. Due to my medical problem, i have decided to donate my life savings to the service of humanity, hence i am looking for someone of integrity who will help carry out my last wishes the way i will advise herein. I took this decision to contact you because I don’t want my husband’s wish to be wasted by unbelievers or someone not to be trusted.
I am not afraid of death hence I know where I am going. I know that I am going to be in the bosom of the Lord. Exodus 14 VS 14 says that the lord will fight my case and I shall hold my peace. Please let me know you can handle this evangelism so that i will provide you more information. Whoever that wants to serve the Lord must serve him in spirit and truth. Please always be prayerful all through your life. If you can handle this, get back to me immediately with your following contacts and detail informations.
Full name:
Address:
Phone Number:
Occupation:
Hope to hear from you.
Remain blessed in the name of the Lord,
From: Mrs. Teresa Albert
In short, “I’m about to die and don’t want to leave this world without first sending out some spam.”
If you own a Mac and haven’t discovered Alfred 2 yet, well I’m sorry. Combined with its PowerPack, it’s a formidable tool for doing things quickly on the Mac. I’ve used QuickSilver and LaunchBar. I held out for a long time as a staunch LaunchBar user, but recently made the switch to Alfred 2 and I’ve got it doing anything everything I need (and boy do I need a lot… I’m lazy and I’ll love keyboard shortcuts). The only shortcoming with Alfred is its clipboard history, which is limited to text (no images… bummer). LaunchBar does the clipboard history just right, so I map Alt+Cmd+K to LaunchBar’s clipboard history and I’m good to go. Sure, LaunchBar is an expensive tool just for clipboard history, but I already owned it and why use Alfred’s crappy clipboard history when I have access to LaunchBar? 🙂
Anyway, I thought I’d share a few of my (now ~24) Alfred 2 workflows for anyone interested:
![]() |
Arrows Easily type arrow characters (↑, ↓, ←, →) using HTML entity names: uarr, darr, larr, and rarr. |
![]() |
IRC Cloud Open IRC Cloud in Chrome with irc. If you’ve already got IRC Cloud in a tab, it doesn’t open it in a second tab. |
![]() |
OpenMRS A workflow for OpenMRS developers with a few handy shortcuts.
|
![]() |
Volume Controls Provides some shortcuts for controlling your volume. You thought you were lazy? I know there are dedicated keys for this, but they’re way over there. Alfred shortcuts can be habituated (once learned, you just think and it happens) and don’t require your hands to leave the “home row” of the keyboard.
|
OpenMRS has some basic conventions for its repositories in GitHub (within the openmrs org). Basically, we add four teams to every repo (owners, full committers, partial committers, and repo owners) and we disable wiki & issues on the repo (since we already have a place for wiki & issues).
It’s easy for these things to get overlooked as new repos are added to the org in GitHub, so I made a little Groovy script to manually audit the repos. Nothing fancy and it doesn’t really warrant a repo of its own, but I want to get the code off my laptop… so I’m blogging it. 🙂
The output should look something like this:
$ groovy AuditOpenMRSRepos.groovy
OpenMRS org has 78 repos
Owners team has 78 repos, missing none
Full Committers team has 78 repos, missing none
Partial Committers team has 77 repos, missing none
Repo Owners team has 77 repos, missing none
wikis or issues (should be empty): []
#!/usr/bin/env groovy
import groovyx.net.http.RESTClient
import org.apache.http.*
import org.apache.http.protocol.*
import groovyx.net.http.*
@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.1')
def scriptDir = new File(getClass().protectionDomain.codeSource.location.path).parent
def token = new File("$scriptDir/github.token").text.trim()
// initialze a new builder and give a default URL
def github = new RESTClient( 'https://api.github.com' ).with {
client.addRequestInterceptor(
[process: { HttpRequest request, HttpContext context ->
// using httpbuilders auth mechanism doesn't work, do it manually
request.setHeader("Authorization", "token $token")
}] as HttpRequestInterceptor
)
client.params.setIntParameter('http.connection.timeout', 5000)
client.params.setIntParameter('http.socket.timeout', 5000)
delegate
}
def getNext(response) {
def next = null
for (link in response.getHeaders('Link')?.value[0]?.split(',')) {
def matcher = link =~ /< (.*)\?page=(\d+)>; rel="next"/
if (matcher.matches()) {
next = [url:matcher[0][1], page:matcher[0][2]]
}
}
next
}
def fromGithub = { path ->
def resp = github.get(path: path, headers:['User-Agent':'Groovy'])
def data = resp.data
def next = getNext(resp)
while (next) {
resp = github.get(path: next.url, query:[page: next.page], headers:['User-Agent':'Groovy'])
data += resp.data
next = getNext(resp)
}
data
}
def addRepoToTeam = { repo, team ->
def resp = github.put(path: "/teams/$team.id/repos/openmrs/$repo.name",
headers:['User-Agent':'Groovy'])
}
def editRepo = { repo ->
def body = """{"name":"$repo.name", "has_issues":false, "has_wiki":false}"""
def resp = github.patch(path: "/repos/openmrs/$repo.name", body: body,
requestContentType:ContentType.URLENC, headers:['User-Agent':'Groovy'])
}
repos = fromGithub('/orgs/openmrs/repos')
teams = fromGithub('/orgs/openmrs/teams').findAll{ it.name != 'Transfer Team' && it.name != 'Release-test' }
println "OpenMRS org has ${repos.size()} repos"
for (team in teams) {
teamRepoNames = fromGithub("/teams/$team.id/repos").collect{ it.name }
missing = repos.findAll{ !(it.name in teamRepoNames) && it.name != 'openmrs-core' }
print "$team.name team has ${teamRepoNames.size()} repos, "
println missing.size() > 0 ? "missing from these: ${missing.collect{it.name}}" : "missing none"
for (repo in missing) {
print "fixing..."
addRepoToTeam(repo, team)
println "done."
}
}
wikisOrIssues = repos.findAll{ it.has_wiki || it.has_issues }
println "wikis or issues (should be empty): ${wikisOrIssues.collect{it.name}}"
for (repo in wikisOrIssues) {
print "fixing..."
editRepo(repo)
println "done."
}
Have you ever seen a harvest moon?
Have you ever wondered why the moon looked so big? Is it some sort of refraction of the atmosphere? Actually, it’s just an optical illusion. It’s time for the One-Eyed Pinky Trick!
Notice anything different?
That’s right, the moon is smaller. Don’t believe me? Try it. It works on the sun too (just don’t stare at the sun, ok?).
How does this work? Here’s my theory…
Poof! Optical Illusion busted thanks to the One-Eyed Pinky Trick!
In the process of upgrading the software license for OpenMRS, it seems like a good time to review how we got here and why we’re changing our license. Here’s a brief history of OpenMRS Licensing…
Ok. Let’s stop here for a second. At this point, in 2007, OpenMRS transforms from a shared, unlicensed, pile of code within a public Subversion repository into officially licensed open-source software. So, what is this OpenMRS Public License and where did it come from? With the help of local lawyers, we hired a lawyer with expertise in open source licensing and described our goals:
The lawyer took these goals, reviewed the available open source licenses at the time, and suggested the Mozilla Public License 1.1 with a few tweaks to fit our specific needs. So, we created the OpenMRS Public License 1.0 as a slightly modified version of MPL 1.1 and applied it to all of our code.
In 2013, with some hard work by Paul and help from OSI, Luis Villa, and some other lawyers, we discover that the Mozilla Public License 2.0 with a disclaimer could meet all of our needs, so we proposed the idea to the community. Overall, people in the community are pleased to see us adopting an OSI-approved license.
Okay, OpenMRS on an OSI-approved license… at last. That’s cool. But why Mozilla Public License 2.0 (MPL 2.0)?
See our license at http://openmrs.org/license.
I was recently reminded of the quote that so often is (mis)attributed to St. Francis of Assisi:
Without getting religious, I believe and hope OpenMRS follows this dictum: spend more time & effort improving health in resource poor environments than we spend talking about it. And, for OpenMRS, we choose to do our work openly. Why? Because “Open Source” is not so much about sharing code as it is about sharing experiences, teaching & learning from each other, and embracing collaboration & open methodologies… in short, open behavior. It took a while to learn that distinction. Now when I hear people fussing over code, it feels petty. One of the most important lessons that I’ve learned from the OpenMRS Community:
We could switch to a completely different programming language or a new shiny platform could (and likely will) come along some day that’s far better than what we’ve done. All of our precious code will fade away. That’s fine. As long as we have our people. Are you running a development shop? Have you calculated how much you’ve invested in your “product” and found yourself thinking about the code? Wrong. Your investment is in people. Give me the choice between good code and a good coder and I will take the coder 100 times out of 100. In the end, code is just a tool… property. And property can be replaced. Love your coders. Treat them well and invest in them. Life will be good. And while you’re doing that, consider working openly.
I recently discovered IRCCloud and it has brought me back to IRC. I no longer have to worry about opening or maintaing a client or an IRC bot. I can check into IRC on my own terms and easily catch up on what I’ve missed (even days of history) with little effort. Perfect!
But it gets better. After a day or so playing around with IRCCloud, I hopped into the feedback channel to give some props to the IRCCloud team and ask some questions. I had noticed that I couldn’t page up/down through the history using the keyboard. Look what happened:
From feature request to deployment in under 4 hours… now that is continuous delivery! Well done, IRCCloud!!!
IRCloud is still in a beta phase. You can sign up, but it might be a while before you get an invite. If you’re looking for an invite to IRCCloud Beta, let me know and I may be able to send you one.
As we work to organize & improve the development work we are doing for OpenMRS, we’re starting to use (and sometimes misuse) a growing list of terminology. I thought I’d dump them out here (to get them out of my head, to be able to come back & look at them, and maybe to get comments from folks on what we’ve got wrong). Many of these are drawn from our (growing) experience with agile methodology. Since I’m not taking the time to look up “official” definitions, I’m sure these are imprecise and I wouldn’t be surprised to learn that we’re doing what others were doing 10 years ago. 🙂
What gets done:
How it gets done:
Who does the work:
Thoughts or comments are welcome.
I wanted to check out OpenMRS trunk and a couple branches from the subversion repository within the same local copy so that I could apply a set of changes to trunk and backport it to a couple prior versions in a single commit. Typically, when you check out a directory, you get everything underneath. But OpenMRS trunk and the branches I wanted are only a few of the bazillion folders and files underneath http://svn.openmrs.org/openmrs/. Checking out all of those folders would take a long time, place an unnecessary tax on the OpenMRS repository, and end up transferring a bazillion files that I didn’t need. While it’s not obvious, there is a way to do this with Subversion. The answer is in Subversions sparse directories feature. Thank you, stackoverflow! Here’s how I checked out only a subset of folders (trunk and a couple branches) from subversion:
$ svn co --depth empty http://svn.openmrs.org/openmrs
$ svn update --set-depth infinity openmrs/trunk
$ svn update --set-depth empty openmrs/branches
$ svn update --set-depth infinity openmrs/branches/1.8.x
$ svn update --set-depth infinity openmrs/branches/1.9.x
After seeing some sample Google Interview Questions that included this question, I couldn’t resist the challenge…
def bigE() {
BigDecimal e = new BigDecimal(1.0G)
BigDecimal temp = new BigDecimal(1.0G)
for (int i in 1..100) {
temp *= i
e += new BigDecimal("1")
.divide(temp, new java.math.MathContext(10000))
}
return e.toString()
}
def isPrime(long n) {
if (n < 2) return false
if (n == 2 || n == 3) return true
if (n%2 == 0 || n%3 == 0) return false
long sqrtN = (long)Math.sqrt(n)+1
for (long i=6L; i < sqrtN; i += 6) {
if (n%(i-1) == 0 || n%(i+1) == 0) return false
}
return true
}
def firstPrimeBySize(n) {
String e = bigE()
for (int i in 2..e.size()-n) {
String chunk = e.substring(i,i+n)
if (isPrime(new BigDecimal(chunk).toLong())) {
return "$chunk at position $i"
}
}
}
assert firstPrimeBySize(10) == "7427466391 at position 100"