Skip to content
This repository has been archived by the owner on Sep 1, 2020. It is now read-only.

Commit

Permalink
Add bin/oven, update readme, change function name.
Browse files Browse the repository at this point in the history
  • Loading branch information
brianloveswords committed Mar 8, 2013
1 parent f2f99e3 commit 0b43aee
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 27 deletions.
55 changes: 51 additions & 4 deletions README.md
@@ -1,8 +1,55 @@
# openbadges-bakery [![Build Status](https://secure.travis-ci.org/mozilla/openbadges-bakery.png)](http://travis-ci.org/mozilla/openbadges-bakery)

Provides two methods:
# Install
```bash
$ npm install openbadges-bakery
```
# CLI Usage

## Baking

```bash
$ oven [--in path/to/image.png] [--out path/to/baked-image.png] <data>
```
If `--out` is not set, the baked image will print to stdout.

The input file can also be piped into stdin.

```js
bakery.bake(buffer | stream, callback);
bakery.debake(buffer | stream, callback);
```bash
$ cat path/to/image.png | oven <data> > path/to/baked-image.png
```
## Extracting

```bash
$ oven [--in path/to/image.png] --extract
```

Same as above, you can also pipe a file to stdin. The data will be printed to stdout.

# Libary Usage

## bakery.bake(options callback);

Bakes some data into an image.

Options are
- `image`: either a buffer or a stream representing the PNG to bake
- `data`: the data to put into the badge. At this point, it should likely be a URL pointing to a badge assertion

`callback` has the signature `function(err, imageData)`

## bakery.debake(image, callback);

Gets the URL from a baked badge and attempts to retreive the assertion
at the other end.

`image` should be a stream or a buffer

`callback` has the signature `function (err, object)` where `object` is expected to be a OpenBadges assertion.

## bakery.extract(image, callback)

Gets the data from the baked badge.

`callback` has the signature `function (err, data)`

57 changes: 57 additions & 0 deletions bin/oven
@@ -0,0 +1,57 @@
#!/usr/bin/env node

const fs = require('fs');
const argv = require('optimist').argv;
const stdout = process.stdout;
const stdin = process.stdin;
const stderr = process.stderr;
const bakery = require('../');
const path = require('path');
const url = argv._[0];
const infile = argv.in||argv.infile;
const outfile = argv.out||argv.outfile;
const extract = argv.extract;

function log(msg) {
stderr.write(msg + '\n');
}

if (!url && !extract) {
log('You must pass a url to bake into the image');
process.exit(1);
}

var stream;
if (infile) {
stream = fs.createReadStream(path.resolve(infile));
} else {
stdin.resume();
stream = stdin;
}

if (extract) {
bakery.extract(stream, function done(err, data) {
if (err) {
log('there was an error:', err.message);
process.exit(1);
}
stdout.write(data + '\n');
process.exit(1);
})
}

bakery.bake({
image: stream,
url: url
}, function done(err, baked) {
if (err) {
log('there was an error:', err.message);
process.exit(1);
}
if (outfile) {
fs.writeFileSync(path.resolve(outfile), baked)
} else {
stdout.write(baked);
}
process.exit(0);
});
38 changes: 20 additions & 18 deletions lib/bakery.js → index.js
Expand Up @@ -6,12 +6,12 @@
* Licensed under the MPL 2.0 license.
*/

var util = require('util');
var streampng = require('streampng');
var request = require('request');
var urlutil = require('url');
const util = require('util');
const streampng = require('streampng');
const request = require('request');
const urlutil = require('url');

var KEYWORD = 'openbadges';
const KEYWORD = 'openbadges';

function createChunk(url) {
return streampng.Chunk.tEXt({
Expand All @@ -21,29 +21,31 @@ function createChunk(url) {
}

exports.bake = function bake(options, callback) {
var buffer = options.image;
var png = streampng(buffer);
// #TODO: make sure the url is set
var chunk = createChunk(options.url);
const buffer = options.image;
const data = options.url || options.data;
const png = streampng(buffer);
const chunk = createChunk(data);
var existingChunk;
if (!data)
return callback(new Error('must pass a `data` or `url` option'));
png.inject(chunk, function (txtChunk) {
if (txtChunk.keyword === KEYWORD) {
existingChunk = txtChunk;
return false;
}
});
if (existingChunk) {
var msg = util.format('This image already has a chunk with the `%s` keyword (contains: %j)', KEYWORD, chunk.text);
var error = new Error(msg);
const msg = util.format('This image already has a chunk with the `%s` keyword (contains: %j)', KEYWORD, chunk.text);
const error = new Error(msg);
error.code = 'IMAGE_ALREADY_BAKED';
error.contents = existingChunk.text;
return callback(error);
}
return png.out(callback);
};

exports.getBakedData = function getBakedData(img, callback) {
var png = streampng(img);
exports.extract = function extract(img, callback) {
const png = streampng(img);
var found = false;

function textListener(chunk) {
Expand All @@ -56,7 +58,7 @@ exports.getBakedData = function getBakedData(img, callback) {

function endListener() {
if (!found) {
var error = new Error('Image does not have any baked in data.');
const error = new Error('Image does not have any baked in data.');
error.code = 'IMAGE_UNBAKED';
return callback(error);
}
Expand All @@ -68,7 +70,7 @@ exports.getBakedData = function getBakedData(img, callback) {


exports.debake = function debake(image, callback) {
exports.getBakedData(image, function (error, url) {
exports.extract(image, function (error, url) {
if (error)
return callback(error);

Expand All @@ -78,8 +80,8 @@ exports.debake = function debake(image, callback) {
return callback(error);
}

var status = response.statusCode;
var type = response.headers['content-type'];
const status = response.statusCode;
const type = response.headers['content-type'];

if (status == 200 && type == 'application/json')
return exports.parseResponse(body, url, callback);
Expand All @@ -104,7 +106,7 @@ exports.parseResponse = function parseResponse(body, url, callback) {
return callback(null, obj);
};

var errors = {
const errors = {
request: function (original, url) {
var msg = util.format('There was an error initiating the request: %s', original.message);
var error = new Error(msg);
Expand Down
6 changes: 4 additions & 2 deletions package.json
Expand Up @@ -2,13 +2,15 @@
"name": "openbadges-bakery",
"version": "0.1.1",
"description": "Tools for baking and debaking openbadge images",
"main": "lib/bakery.js",
"main": "index.js",
"directories": {
"test": "test"
},
"bin": "bin/oven",
"dependencies": {
"request": "~2.11.4",
"streampng": "~0.1.1"
"streampng": "~0.1.1",
"optimist": "~0.3.5"
},
"devDependencies": {
"oneshot": "~0.1.0",
Expand Down
6 changes: 3 additions & 3 deletions test/bakery.test.js
Expand Up @@ -5,7 +5,7 @@ var pathutil = require('path');
var urlutil = require('url');
var oneshot = require('oneshot');

var bakery = require('../lib/bakery');
var bakery = require('..');

var IMG_PATH = pathutil.join(__dirname, 'testimage.png');
var ASSERTION_URL = "http://example.org";
Expand Down Expand Up @@ -70,7 +70,7 @@ test('bakery.bake: takes a buffer', function (t) {
bakery.bake(options, function (err, baked) {
t.notOk(err, 'should not have an error');
t.ok(baked, 'should get back some data');
bakery.getBakedData(baked, function (err, url) {
bakery.extract(baked, function (err, url) {
t.notOk(err, 'there should be a matching tEXt chunk');
t.same(url, ASSERTION_URL, 'should be able to find the url');
t.end();
Expand All @@ -87,7 +87,7 @@ test('bakery.bake: takes a stream', function (t) {
bakery.bake(options, function (err, baked) {
t.notOk(err, 'should not have an error');
t.ok(baked, 'should get back some data');
bakery.getBakedData(baked, function (err, url) {
bakery.extract(baked, function (err, url) {
t.notOk(err, 'there should be a matching tEXt chunk');
t.same(url, ASSERTION_URL, 'should be able to find the url');
t.end();
Expand Down
Binary file added test/unbaked.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 0b43aee

Please sign in to comment.