Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/thundercomb/poetrydb

The Internet's first Poetry API
https://github.com/thundercomb/poetrydb

Last synced: 3 months ago
JSON representation

The Internet's first Poetry API

Lists

README

        

# PoetryDB

## Introduction

PoetryDB is an API for internet poets. But what is an API?

An API ensures that a program (such as a browser) always returns data in an expected format. JSON is one of the most popular formats in use today.

"Why should poets care?" [The answer](https://thecombedthunderclap.blogspot.co.uk/2014/03/kenneth-goldsmith-and-uncreative-writing.html) is blowing in the data winds. Internet technology is making words endlessly manipulable, and traditional poets and writers are getting left behind. I want to change this, by giving us all a leg up into a more empowered future.

How does it work?

You send a URL like [so](https://poetrydb.org/title/Ozymandias/lines.json):

```
https://poetrydb.org/title/Ozymandias/lines.json
```

And hey, presto! out comes the lines of Shelley's famous sonnet:

```
[
{
"lines": [
"I met a traveller from an antique land",
"Who said: \"Two vast and trunkless legs of stone",
"Stand in the desert. Near them on the sand,",
"Half sunk, a shattered visage lies, whose frown",
"And wrinkled lip and sneer of cold command",
"Tell that its sculptor well those passions read",
"Which yet survive, stamped on these lifeless things,",
"The hand that mocked them and the heart that fed.",
"And on the pedestal these words appear:",
"'My name is Ozymandias, King of Kings:",
"Look on my works, ye mighty, and despair!'",
"Nothing beside remains. Round the decay",
"Of that colossal wreck, boundless and bare,",
"The lone and level sands stretch far away\"."
]
}
]
```

But what do we do with text in json format? The real power of PoetryDB's API becomes apparent when combined with a program. Consider the following Ruby code:

```
require 'httparty'

response = HTTParty.get("https://poetrydb.org/author,linecount/Shakespeare;14/lines").to_a
(0..13).each { |i| puts response[rand(154)]['lines'][i] }
```

This fairly simple code is capable of surprising poetry! The program asks PoetryDB for all poems that are 14 lines in length, then writes out a new sonnet based on the results. Astute readers will know that this is the first step towards creating your own version of Raymond Queneau's [One Hundred Thousand Billion Sonnets](http://www.bevrowe.info/Queneau/QueneauRandom_v5.html), this time based on some of the most beautiful lines ever written in the English language.

Here is an example:

```
Since I left you, mine eye is in my mind;
Full character'd with lasting memory,
The rose looks fair, but fairer we it deem
For that sweet odour, which doth in it live.
Yet, in good faith, some say that thee behold,
Thy face hath not the power to make love groan;
But the defendant doth that plea deny,
By seeing farther than the eye hath shown.
Thou art the grave where buried love doth live,
It is my love that keeps mine eye awake:
Are windows to my breast, where-through the sun
Unless thou take that honour from thy name:
Therefore I lie with her, and she with me,
Compar'd with loss of thee, will not seem so.
```

## Architecture and code

The API is written in Ruby and uses Sinatra to resolve API routes. The poetry data is stored in a MongoDB database. The Ruby code is provided here as Open Source. The PoetryDB database is not directly accessible, in order to preserve its integrity.

![Architecture Diagram](https://github.com/thundercomb/poetrydb/blob/master/Architecture_Diagram.jpg)

## API Reference

General format of API:

```
//[;][..][:][/][,][..][.]
```

* `````` can be one of:

```author```: The name, or part of the name, of the author of a poem
```title```: The title, or part of the title, of a poem
```lines```: Part of a line or lines of a poem
```linecount```: The number of lines of a poem, including section headings, but excluding empty lines (eg. section breaks)
```poemcount```: The number of poems to return (cannot be used in combination with `random`)
```random```: The number of random poems to return (cannot be used in combination with `poemcount`)

* `````` relates to ``````. When `````` is:

```author```: `````` is the name, or part of the name, of the author of a poem
```title```: `````` is the title, or part of the title, of a poem
```lines```: `````` is part of a line or lines of a poem
```linecount```: `````` is the number of lines of a poem. Number of lines includes section headings, but excludes empty lines (eg. section breaks)
```poemcount```: `````` is the number of poems to return
```random```: `````` is the number of random poems to return

* ```[:]``` is optional. It can be:

```:abs```: Match `````` exactly when searching ``````
```Default (empty)```: match `````` with any part of `````` when searching

* ```[/][,][..]``` are optional. They are a comma delimited set that can be any combination of:

```author```: Return only the author of each of the matching poems
```title```: Return only the title of each of the matching poems
```lines```: Return only the lines of each of the matching poems
```linecount```: Return only the number of lines of each of the matching poems
```author,title,...```: Return each output field in the comma delimited list of each of the matching poems
```Default (empty)```: Return all data of each of the matching poems

or:

```all```: Return all data of the matching poems (same as ```Default (empty)```)

* ```[.]``` is optional. It can be:

```.json```: Return data in json format
```.text```: Return data in text format
```Default (empty)```: Return data in json format

* ```[..]``` means that by using the same syntax, more instances of the preceding type can be expressed

### Author

General Format:
```
/author[/][:abs][/][,][..][.]
```

Format:
```
/author
```
Example:
```
/author
```
Result:
```
{
"authors": [
"Adam Lindsay Gordon",
"Alan Seeger",
"Alexander Pope",
"Algernon Charles Swinburne",
.
.
"William Shakespeare",
"William Topaz McGonagall",
"William Vaughn Moody",
"William Wordsworth"
]
}
```

Format:
```
/author/
```
Example:
```
/author/Ernest Dowson
```
Result:
```
[
{
"title": "The Moon Maiden's Song",
"author": "Ernest Dowson",
"lines": [
"Sleep! Cast thy canopy",
" Over this sleeper's brain,",
"Dim grow his memory,",
" When he wake again.",
"",
"Love stays a summer night,",
" Till lights of morning come;",
"Then takes her winged flight",
" Back to her starry home.",
"",
"Sleep! Yet thy days are mine;",
" Love's seal is over thee:",
"Far though my ways from thine,",
" Dim though thy memory.",
"",
"Love stays a summer night,",
" Till lights of morning come;",
"Then takes her winged flight",
" Back to her starry home."
],
"linecount": 16
}
]
```

Format:
```
/author//author
```
Example:
```
/author/owson/author
```
Result:
```
[
{
"author": "Ernest Dowson"
}
]
```

Format:
```
/author/:abs/author
```
Example:
```
/author/Ernest Dowson:abs/author
```
Result:
```
[
{
"author": "Ernest Dowson"
}
]
```

Format:
```
/author//,,
```
Example:
```
/author/Ernest Dowson/author,title,linecount
```
Result:
```
[
{
"title": "The Moon Maiden's Song",
"author": "Ernest Dowson",
"linecount": 16
}
]
```

Format:
```
/author//,,.
```
Example:
```
/author/Ernest Dowson/author,title,linecount.text
```
Result:
```
title
The Moon Maiden's Song
author
Ernest Dowson
linecount
16
```

### Title

General Format:
```
/title[/][:abs][/][,][..][.]
```

Format:
```
/title
```
Example:
```
/title
```
Result:
```
{
"titles": [
"A Baby's Death",
"A Ballad Of The Trees And The Master",
"A Ballad of Burdens",
"A Ballad of Death",
.
.
"You know that Portrait in the Moon --",
"You see I cannot see -- your lifetime",
"Young Munro the Sailor",
"Youth And Age"
]
}
```

Format:
```
/title/
```
Example:
```
/title/Ozymandias
```
Result:
```
[
{
"title": "Ozymandias",
"author": "Percy Bysshe Shelley",
"lines": [
"I met a traveller from an antique land",
"Who said: \"Two vast and trunkless legs of stone",
"Stand in the desert. Near them on the sand,",
"Half sunk, a shattered visage lies, whose frown",
"And wrinkled lip and sneer of cold command",
"Tell that its sculptor well those passions read",
"Which yet survive, stamped on these lifeless things,",
"The hand that mocked them and the heart that fed.",
"And on the pedestal these words appear:",
"'My name is Ozymandias, King of Kings:",
"Look on my works, ye mighty, and despair!'",
"Nothing beside remains. Round the decay",
"Of that colossal wreck, boundless and bare,",
"The lone and level sands stretch far away\"."
],
"linecount": 14
}
]
```

Format:
```
/title//title
```
Example:
```
/title/spring/title
```
Result:
```
[
{
"title": "I have a Bird in spring"
},
{
"title": "A spring poem from bion"
},
{
"title": "Nay, Lord, not thus! white lilies in the spring,"
},
{
"title": "In spring and summer winds may blow"
},
{
"title": "Sonnet 98: From you have I been absent in the spring"
}
]
```

Format:
```
/title/:abs/title
```
Example:
```
/title/In spring and summer winds may blow:abs/title
```
Result:
```
[
{
"title": "In spring and summer winds may blow"
}
]
```

Format:
```
/title//,,
```
Example:
```
/title/Ozymandias/author,title,linecount
```
Result:
```
[
{
"title": "Ozymandias",
"author": "Percy Bysshe Shelley",
"linecount": 14
}
]
```

Format:
```
/title//,,.
```
Example:
```
/title/Ozymandias/title,lines.text
```
Result:
```
title
Ozymandias
lines
I met a traveller from an antique land
Who said: "Two vast and trunkless legs of stone
Stand in the desert. Near them on the sand,
Half sunk, a shattered visage lies, whose frown
And wrinkled lip and sneer of cold command
Tell that its sculptor well those passions read
Which yet survive, stamped on these lifeless things,
The hand that mocked them and the heart that fed.
And on the pedestal these words appear:
'My name is Ozymandias, King of Kings:
Look on my works, ye mighty, and despair!'
Nothing beside remains. Round the decay
Of that colossal wreck, boundless and bare,
The lone and level sands stretch far away".
```

### Lines

General Format:
```
/lines/[:abs][/][,][..][.]
```

Format:
```
/lines/
```
Example:
```
/lines/Latitudeless Place
```
Result:
```
[
{
"title": "Now I knew I lost her --",
"author": "Emily Dickinson",
"lines": [
"Now I knew I lost her --",
"Not that she was gone --",
"But Remoteness travelled",
"On her Face and Tongue.",
"",
"Alien, though adjoining",
"As a Foreign Race --",
"Traversed she though pausing",
"Latitudeless Place.",
"",
"Elements Unaltered --",
"Universe the same",
"But Love's transmigration --",
"Somehow this had come --",
"",
"Henceforth to remember",
"Nature took the Day",
"I had paid so much for --",
"His is Penury",
"Not who toils for Freedom",
"Or for Family",
"But the Restitution",
"Of Idolatry."
],
"linecount": 20
}
]
```

Format:
```
/lines//
```
Example:
```
/lines/Latitudeless Place/author
```
Result:
```
[
{
"author": "Emily Dickinson"
}
]
```

Format:
```
/lines//,,
```
Example:
```
/lines/Latitudeless Place/author,title,linecount
```
Result:
```
[
{
"title": "Now I knew I lost her --",
"author": "Emily Dickinson",
"linecount": 20
}
]
```

Format:
```
/lines//,,.
```
Example:
```
/lines/Latitudeless Place/author,title,linecount.text
```
Result:
```
title
Now I knew I lost her --
author
Emily Dickinson
linecount
20
```

### Linecount

General Format:
```
/linecount/[/][,][..][.]
```

Note: linecount is always exact, and therefore the match type ```:abs``` has no effect.

Format:
```
/linecount/
```
Example:
```
/linecount/3
```
Result:
```
[
{
"title": "Of Life to own --",
"author": "Emily Dickinson",
"lines": [
"Of Life to own --",
"From Life to draw --",
"But never tough the reservoir --"
],
"linecount": 3
},
{
"title": "A Flower will not trouble her, it has so small a Foot,",
"author": "Emily Dickinson",
"lines": [
"A Flower will not trouble her, it has so small a Foot,",
"And yet if you compare the Lasts,",
"Hers is the smallest Boot --"
],
"linecount": 3
},
{
"title": "To see the Summer Sky",
"author": "Emily Dickinson",
"lines": [
"To see the Summer Sky",
"Is Poetry, though never in a Book it lie --",
"True Poems flee --"
],
"linecount": 3
}
]
```

Format:
```
/linecount//
```
Example:
```
/linecount/3/title
```
Result:
```
[
{
"title": "Of Life to own --"
},
{
"title": "A Flower will not trouble her, it has so small a Foot,"
},
{
"title": "To see the Summer Sky"
}
]
```

Format:
```
/linecount//,,
```
Example:
```
/linecount/51/author,title,linecount
```
Result:
```
[
{
"title": "On the Death of the Rev. Dr. Sewell",
"author": "Phillis Wheatley",
"linecount": 51
},
{
"title": "A Letter to a Live Poet",
"author": "Rupert Brooke",
"linecount": 51
}
]
```

Format:
```
/linecount//,.
```
Example:
```
/linecount/39/author,title.text
```
Result:
```
title
In Winter in my Room
author
Emily Dickinson

title
Celestial Music
author
John Donne

title
Life
author
Robinson

title
29. Song—The Rigs o’ Barley
author
Robert Burns

title
Edinburgh
author
William Topaz McGonagall
```

### Poemcount

General Format:
```
/[,][..],poemcount/[;[/][,][..][.]
```

Notes:
- although poemcount can be provided on its own, it makes sense mainly when combined with other input fields
- poemcount is always exact, and therefore the match type ```:abs``` has no effect
- poemcount and random cannot be used together, as both specify the number of poems to return

Format:
```
/,poemcount/;
```
Example:
```
/author,poemcount/Dickinson;2
```
Result:
```
[
{
"title": "Not at Home to Callers",
"author": "Emily Dickinson",
"lines": [
"Not at Home to Callers",
"Says the Naked Tree --",
"Bonnet due in April --",
"Wishing you Good Day --"
],
"linecount": "4"
},
{
"title": "Defrauded I a Butterfly --",
"author": "Emily Dickinson",
"lines": [
"Defrauded I a Butterfly --",
"The lawful Heir -- for Thee --"
],
"linecount": "2"
}
]
```

Format:
```
/,poemcount/;/
```
Example:
```
/author,poemcount/Dickinson;2/title
```
Result:
```
[
{
"title": "Not at Home to Callers"
},
{
"title": "Defrauded I a Butterfly --"
}
]
```

Format:
```
/,poemcount/;/,,
```
Example:
```
/author,poemcount/Dickinson;2/author,title,linecount
```
Result:
```
[
{
"title": "Not at Home to Callers",
"author": "Emily Dickinson",
"linecount": "4"
},
{
"title": "Defrauded I a Butterfly --",
"author": "Emily Dickinson",
"linecount": "2"
}
]
```

Format:
```
/,poemcount/;/,.
```
Example:
```
/author,poemcount/Dickinson;2/author,title.text
```
Result:
```
title
Not at Home to Callers
author
Emily Dickinson

title
Defrauded I a Butterfly --
author
Emily Dickinson
```

### Random

General Format:
```
/random[/][/][,][..][.]
```

Note:
- the random count search field is always exact, and therefore the match type ```:abs``` has no effect
- random and poemcount cannot be used together, as both specify the number of poems to return

Format:
```
/random
```
Example:
```
/random
```
Result:
```
[
{
"title": "Sonnet XLIV: Press'd by the Moon",
"author": "Charlotte Smith",
"lines": [
"Press'd by the Moon, mute arbitress of tides,",
"While the loud equinox its power combines,",
"The sea no more its swelling surge confines,",
"But o'er the shrinking land sublimely rides.",
"The wild blast, rising from the Western cave,",
"Drives the huge billows from their heaving bed;",
"Tears from their grassy tombs the village dead,",
"And breaks the silent sabbath of the grave!",
"With shells and sea-weed mingled, on the shore",
"Lo! their bones whiten in the frequent wave;",
"But vain to them the winds and waters rave;",
"They hear the warring elements no more:",
"While I am doom'd—by life's long storm opprest,",
"To gaze with envy on their gloomy rest."
],
"linecount": "14"
}
]
```

Format:
```
/random/
```
Example:
```
/random/3
```
Result:
```
[
{
"title": "421. Epitaph on a Lap-dog",
"author": "Robert Burns",
"lines": [
"IN wood and wild, ye warbling throng,",
" Your heavy loss deplore;",
"Now, half extinct your powers of song,",
" Sweet Echo is no more.",
.
.
.
],
"linecount": "8"
},
{
"title": "The Canterbury Tales. The Manciple's Tale.",
"author": "Geoffrey Chaucer",
"lines": [
"THE PROLOGUE.",
"",
"WEET ye not where there stands a little town,",
"Which that y-called is Bob-up-and-down,",
"Under the Blee, in Canterbury way?",
"There gan our Hoste for to jape and play,",
.
.
.
],
"linecount": "364"
},
{
"title": "Love",
"author": "Percy Bysshe Shelley",
"lines": [
"Why is it said thou canst not live",
"In a youthful breast and fair,",
"Since thou eternal life canst give,",
"Canst bloom for ever there?",
.
.
.
],
"linecount": "24"
}
]
```

Format:
```
/random//
```
Example:
```
/random/3/title
```
Result:
```
[
{
"title": "130. Nature’s Law: A Poem"
},
{
"title": "Longings for Home."
},
{
"title": "Buried Life, The"
}
]
```

Format:
```
/random//,,
```
Example:
```
/random/3/author,title,linecount
```
Result:
```
[
{
"title": "The Baby's Dance",
"author": "Ann Taylor",
"linecount": "8"
},
{
"title": "478. Epigram on a Suicide",
"author": "Robert Burns",
"linecount": "4"
},
{
"title": "Reply to Some Verses of J. M. B. Pigot, Esq., on the Cruelty of His Mistress",
"author": "George Gordon, Lord Byron",
"linecount": "48"
}
]
```

Format:
```
/random//,.
```
Example:
```
/random/3/author,title.text
```
Result:
```
title
Pain In Pleasure
author
Elizabeth Barrett Browning

title
The Heaven vests for Each
author
Emily Dickinson

title
Sonnet XXXIX: Prepare Your Wreaths
author
Robinson
```

### Combinations

General Format:
```
/,[,][..]/;[;][,][..][.]
```

Notes:
1. The number of input fields should always be matched by the number of search terms
2. The search terms are separated by the semicolon to allow commas to be used in search terms. However, semicolons are a feature of many texts, and unfortunately cannot be part of the search term currently.

Format:
```
/,/;
```
Example:
```
/title,random/Sonnet;3
```
Result:
```
[
{
"title": "Sonnet 63: Against my love shall be as I am now",
"author": "William Shakespeare",
"lines": [
"Against my love shall be as I am now,",
"With Time's injurious hand crush'd and o'erworn;",
"When hours have drain'd his blood and fill'd his brow",
"With lines and wrinkles; when his youthful morn",
.
.
.
],
"linecount": "14"
},
{
"title": "Sonnet 69: Those parts of thee that the world's eye doth view",
"author": "William Shakespeare",
"lines": [
"Those parts of thee that the world's eye doth view",
"Want nothing that the thought of hearts can mend;",
"All tongues--the voice of souls--give thee that due,",
"Uttering bare truth, even so as foes commend.",
.
.
.
],
"linecount": "14"
},
{
"title": "Sonnet XVII: His Mother Dear Cupid",
"author": "Sir Philip Sidney",
"lines": [
"His mother dear Cupid offended late,",
"Because that Mars grown slacker in her love,",
"With pricking shot he did not throughly more",
"To keep the pace of their first loving state.",
.
.
.
],
"linecount": "14"
}
]
```

@@@@
Format:
```
/,,/;;
```
Example:
```
/title,author,linecount/Winter;Shakespeare;18
```
Result:
```
[
{
"title": "Spring and Winter ii",
"author": "William Shakespeare",
"lines": [
"WHEN icicles hang by the wall,",
" And Dick the shepherd blows his nail,",
"And Tom bears logs into the hall,",
" And milk comes frozen home in pail,",
.
.
.
],
"linecount": 18
},
{
"title": "Spring and Winter i",
"author": "William Shakespeare",
"lines": [
"WHEN daisies pied and violets blue,",
" And lady-smocks all silver-white,",
"And cuckoo-buds of yellow hue",
" Do paint the meadows with delight,",
.
.
.
],
"linecount": 18
},
{
"title": "Winter",
"author": "William Shakespeare",
"lines": [
"When icicles hang by the wall",
"And Dick the shepherd blows his nail",
"And Tom bears logs into the hall,",
"And milk comes frozen home in pail,",
.
.
.
],
"linecount": 18
}
]
```

Format:
```
/,/:abs;
```

Example:
```
/title,author/Winter:abs;William%20Shakespeare
```
Result:
```
[
{
"title": "Winter",
"author": "William Shakespeare",
"lines": [
"When icicles hang by the wall",
"And Dick the shepherd blows his nail",
"And Tom bears logs into the hall,",
"And milk comes frozen home in pail,",
"When Blood is nipped and ways be foul,",
"Then nightly sings the staring owl,",
"Tu-who;",
"Tu-whit, tu-who: a merry note,",
"While greasy Joan doth keel the pot.",
"",
"When all aloud the wind doth blow,",
"And coughing drowns the parson's saw,",
"And birds sit brooding in the snow,",
"And Marian's nose looks red and raw",
"When roasted crabs hiss in the bowl,",
"Then nightly sings the staring owl,",
"Tu-who;",
"Tu-whit, tu-who: a merry note,",
"While greasy Joan doth keel the pot."
],
"linecount": 18
}
]
```
Format:
```
/,,,/;;;
```

Example:
```
/title,author,linecount,poemcount/Winter;William Shakespeare;14;1
```
Result:
```
[
{
"title": "Sonnet 2: When forty winters shall besiege thy brow",
"author": "William Shakespeare",
"lines": [
"When forty winters shall besiege thy brow,",
"And dig deep trenches in thy beauty's field,",
"Thy youth's proud livery so gazed on now,",
"Will be a tatter'd weed of small worth held:",
"Then being asked, where all thy beauty lies,",
"Where all the treasure of thy lusty days;",
"To say, within thine own deep sunken eyes,",
"Were an all-eating shame, and thriftless praise.",
"How much more praise deserv'd thy beauty's use,",
"If thou couldst answer 'This fair child of mine",
"Shall sum my count, and make my old excuse,'",
"Proving his beauty by succession thine!",
" This were to be new made when thou art old,",
" And see thy blood warm when thou feel'st it cold."
],
"linecount": "14"
}
]
```
Format:
```
/,/;/
```
Example:
```
/title,author/Winter;William Shakespeare/title
```
Result:
```
[
{
"title": "Spring and Winter ii"
},
{
"title": "Spring and Winter i"
},
{
"title": "Blow, Blow, Thou Winter Wind"
},
{
"title": "Winter"
}
]
```
Format:
```
/,/;/[.]
```
Example:
```
/title,author/Winter;William Shakespeare/title.text
```
Result:
```
title
Spring and Winter ii

title
Spring and Winter i

title
Blow, Blow, Thou Winter Wind

title
Winter
```

## Contact

Let me know of any documentation, bugs, or missing features you would like to see, or just come and say hi, on Twitter @po3db

## License

To protect the openness of this endeavour the software is released under the terms of the [GNU Public License v2](https://github.com/thundercomb/poetrydb/blob/master/LICENSE.txt). In essence it allows you to reuse and modify this software, as long as the resulting program(s) remain open and licensed in the same way.