I’ve been using Zen Quotes API for a while now. It’s a great app that provides quotes for my lockscreen. But to filter based on Author, I need to pay for the premium version. So I decided to create my own personal quote API.
First I needed a source of quotes. I found datasets of quotes on Kaggle Quotes Dataset and Quotes-500K. I think these datasets were created by scraping the web for quotes.
The Plan
- Create
sqlite
database to store quotes. - Create table
quotes
with columnsquote
,author
,tags
. - Import quotes from the dataset.
- Perform READ operations on the database. easy peasy.
The Implementation
The problem is that one dataset is in csv
format and the other is in json
format. We need a common format to import the quotes into the database. I decided to convert the json
dataset to csv
format. Time to flex my command-line-fu.
First, I opened the csv
dataset in LibreOffice Calc
and replaced ', '
with ' '
in categories
column. Then renamed categories
to tags
. Saved the file as quotes.csv
.
Next, I converted the json
dataset to csv
using shitty bash-fu.
jq '.[] | "\(.Quote)<merge>, \(.Author)<merge>, \(.Tags | join(" "))"' quotes.json \
| sed "s/<merge>, /\", \"/g" \
| sed -z "s/ \"\n/\"\n/g" >> quotes.csv
.[]
selects each object in the array."\(.Quote)<merge>, \(.Author)<merge>, \(.Tags | join(" "))"
formats the output asquote, author, tags
. I could not find a way to insert double quotes around the fields injq
. So I used keyword to replace with", "
later.🤪sed "s/<merge>, /\", \"/g"
replaces<merge>,
with",
.sed -z "s/ \"\n/\"\n/g"
removes the trailing space before newline.
Now I have a csv
file with quotes. Time to create the database.
sqlite3 ~/playground/quotes/quotes.db
-- Create a database to store quotes.
CREATE TABLE quotes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
quote TEXT,
author TEXT,
tags TEXT
);
-- Import quotes from the `csv` file.
.mode csv
.import quotes.csv quotes
-- Let's count the number of quotes in the database.
SELECT COUNT(*) FROM quotes;
-- 548102 😎
Get a random quote
sqlite3 ~/playground/quotes/quotes.db "SELECT quote FROM quotes ORDER BY RANDOM() LIMIT 1;"
Get a random quote from ‘Socrates’
sqlite3 ~/playground/quotes/quotes.db "SELECT quote FROM quotes WHERE author LIKE '%socrates%' ORDER BY RANDOM() LIMIT 1;"
Now I can get personalized quotes for my lockscreen.
#!/usr/bin/env bash
get_quote() {
sqlite3 -separator " - " ~/playground/quotes/quotes.db \
"SELECT quote, REPLACE(author, '\"', '') AS author FROM quotes \
WHERE ( \
author LIKE '%socrates%' \
OR author LIKE '%plato%' \
OR author LIKE '%aristotle%' \
OR author LIKE '%seneca%' \
OR author LIKE '%epictetus%' \
OR author LIKE '%marcus aurelius%' \
OR author LIKE '%montaigne%' \
OR author LIKE '%schopenhauer%' \
OR author LIKE '%nietzsche%' \
OR author LIKE '%diogenes%' \
OR author LIKE '%kierkegaard%' \
OR author LIKE '%pythagoras%' \
) \
AND LENGTH(quote) < 100 \
ORDER BY RANDOM() LIMIT 1;"
}
if [ ! -f /tmp/__quote_data ]; then
get_quote > /tmp/__quote_data
fi
if [ $(find /tmp/__quote_data -mmin +1) ]; then
previous_quote_data=$(cat /tmp/__quote_data)
rm /tmp/__quote_data
get_quote > /tmp/__quote_data
fi
quote_data=$(cat /tmp/__quote_data)
echo "📜 $quote_data"