Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Airtable Connection #7

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
node_modules/
/dist
/.vscode
/.vscode
.env
./src/site/_data/dev/sheet.json
token.json
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "telegram-site-via-sheet",
"name": "Microblog",
"version": "0.0.1",
"description": "An example of sourcing data from Google Sheets for use in Eleventy at build time",
"description": "An example of sourcing data from Airtable for use in Eleventy at build time",
"author": "Yueh Han Huang",
"license": "MIT",
"scripts": {
Expand All @@ -12,13 +12,14 @@
},
"repository": {
"type": "git",
"url": "https://github.com/Bojne/telegram-to-site"
"url": "https://github.com/Bojne/microblog"
},
"dependencies": {
"@11ty/eleventy": "^0.8.3",
"airtable": "^0.11.1",
"autoprefixer": "^9.6.0",
"axios": "^0.19.0",
"cssnano": "^4.1.10",
"googleapis": "39",
"html-minifier": "^4.0.0"
},
"devDependencies": {
Expand Down
1 change: 0 additions & 1 deletion src/site/_data/dev/sheet.json

This file was deleted.

56 changes: 56 additions & 0 deletions src/site/_data/prod/airtable_source.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const seed = require("../../../utils/save-seed.js");
var Airtable = require("airtable");
Airtable.configure({
endpointUrl: "https://api.airtable.com",
apiKey: process.env.AIRTABLE_API_KEY,
});
const AIRTABLE_API_KEY = process.env.AIRTABLE_API_KEY;
if (!AIRTABLE_API_KEY) {
console.error("No Airtable API key found!");
}
var base = Airtable.base("appcKPyNrw9c9mtYV");
let data = {};

module.exports = function () {
// based on the base(table) id
return new Promise((resolve, reject) => {
base("content")
.select({
// Selecting the first 5 records in Grid view:
maxRecords: 500,
view: "Grid view",
cellFormat: "json",
})
.eachPage(
function page(records, fetchNextPage) {
// This function (`page`) will get called for each page of records.

records.forEach(function (record) {
let type = record.get("type");
if (!(type in data)) {
data[type] = [];
}
data[type].push({
time: record.get("time").split("T"),
message: record.get("message"),
});
// console.log("Retrieved", record.get("type"));
});
// To fetch the next page of records, call `fetchNextPage`.
// If there are more records, `page` will get called again.
// If there are no more records, `done` will get called.
fetchNextPage();
},
function done(err) {
if (err) {
console.error(err);
reject(err);
}
console.log(`Airtable key exist: ${AIRTABLE_API_KEY != null}`);
console.log(`Loading data... 😍`);
seed(JSON.stringify(data), `${__dirname}/../dev/sheet.json`);
resolve(data);
}
);
});
};
12 changes: 12 additions & 0 deletions src/site/_data/prod/credentials.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"type": "service_account",
"project_id": "microblog-338612",
"private_key_id": "45810a9abbae86829cb778a32ae71102f2b92530",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC40MYRAQ94TmbA\n0ICe4h92NlmNvCsKzJAqS/S4jXZFXylg57myNc36SB7jH/HvuE8wMM3GA5YaxDoh\nVN8jPvX7YYyS14IdbCDu4uLYCR/hVahNOPRiMlaOzE2RJQ2+RpHvGQ1XSK/Y3S1u\nHIHQgr1K3dLrn2ds31BzJSrvjbGHq2yZaXOrR0qq43K05Z8yXBRZzP0P7LvNGump\nCB0cbEXPP2USTitpcD3NnNFxhqNpscb134kRjhdc+/V9HUS6ITlQQjVDTfbrBNEs\nDFP6CmWTeyP9oDRF+vFg25mRtvbZslg0QUqpCAq9tzdIAV96RPmh6WhkJttapxw7\nD8pZlcIjAgMBAAECggEAP6aPgI238Tw3QVLN6WqBYWoof5r9y/NV92s/dkwqHow+\nqQRFvS2wqfEqyhhXb7Mveq5kQD099iv8xTwAuZfWieQ30N7uDgoOcZesfrDtzOJ+\nW1IxQJyLmRSd5k43pH+ThSBAqv36qhrKqbChuNk+LkmlecbljOaAQ5faaLSJHusC\nXlcw+Irp7U2iUZYEel9I7nNlYsceVjvUne1ja9xL8hYWpScclYczzOpOo2g0Nyxb\nG0YybAgGsbf3bY9FsVtVvVJkc89B4SV72TqYiNqWiIcfEkKnkwoBlbLj6Nb9ySSe\nuOT/bOoLokqY5hxhGsTVM8dqi6EwllWUOwXTEVJviQKBgQDcNrYQbXW1fo5m2soJ\nRRCYZXd8xq3VWvncyydpeYgJCJtdWK2+eOh1V+XnS04EdY3B4/cEKS8nQh975fB7\nL1F4M3kSSePvopVjhbYGoTWI/o1mL8Hi4HVMj8j9KP2uz+R1iQ//Ymkn3dKg2pUR\nduAWsU/ktgwVvRCbwlON/5NFRwKBgQDW2W8DvrXYogKjw5n3/D8MyIQkJzbKE1S0\nD8s0ZiiNacLFH0mjv4YrM6s8yk64KaJmgHdugTL08IOb3Cvx8lRdIBiW/Tp2s7nx\n+uAQiZnD9+Q1FWH9LKh3zb597MSvMTC7fNdNlzM7s4JUboUkKN5kvfB4PzG8rBHZ\n1AyMHj46RQKBgBG0YFzfwAfwfdhtHLM0F0p5Ver1OkKeBtqmhqunNrWrOHp/x7A5\nnk7Y20YGOuaG4PfGsTRnb0ATw949NWFiA4XLdZ9vy2CXzLTsqh7MVTaHaKzfiBIK\ng8O9B6a65fJpCnAcremVaujmn6mJCVUXHpsUdFzp+fzBb5VmQTt4Ycm/AoGABWjA\nBMYeae/aRSk9jSLKq5W4zfg2xuuprEbhhNY1mynYf4IEJp1B0YChhQxK4xQZRJ9j\nYmLaV5Rem+P1L0g8m4OdWt/RQv/PZKo+TexI9Mge9L8vEmK3cxy4+Q6m/QouAepo\nuUlfPteMJngJ3hkxUDQAA+cDZ46lfGh8UGLKikkCgYAroYl8GmeVrIOALlqqoaSz\nFD3TN0vyO+8mNvsbMc4RxQa0qfVoECrQle3TQAkys0XH3K1R2wx/lDeLNAFbvoCz\nQJ7op1zV9LVZbky4jGJFphX8WNjTo/bz+MJ73YwFi7VEd2B6KrFikWa7r/caxF/l\njRWdP4HbyKe/ayWTHp+lAw==\n-----END PRIVATE KEY-----\n",
"client_email": "[email protected]",
"client_id": "105255691711310260475",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/telegram-sourcing%40microblog-338612.iam.gserviceaccount.com"
}
102 changes: 102 additions & 0 deletions src/site/_data/prod/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
const fs = require("fs");
const readline = require("readline");
const { google } = require("googleapis");

// If modifying these scopes, delete token.json.
const SCOPES = ["https://www.googleapis.com/auth/spreadsheets.readonly"];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = "token.json";

// Load client secrets from a local file.
fs.readFile("credentials.json", (err, content) => {
if (err) return console.log("Error loading client secret file:", err);
// Authorize a client with credentials, then call the Google Sheets API.
authorize(JSON.parse(content), listMajors);
});

/**
* Create an OAuth2 client with the given credentials, and then execute the
* given callback function.
* @param {Object} credentials The authorization client credentials.
* @param {function} callback The callback to call with the authorized client.
*/
function authorize(credentials, callback) {
const { client_secret, client_id, redirect_uris } = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id,
client_secret,
redirect_uris[0]
);

// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return getNewToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}

/**
* Get and store new token after prompting for user authorization, and then
* execute the given callback with the authorized OAuth2 client.
* @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
* @param {getEventsCallback} callback The callback for the authorized client.
*/
function getNewToken(oAuth2Client, callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: "offline",
scope: SCOPES,
});
console.log("Authorize this app by visiting this url:", authUrl);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question("Enter the code from that page here: ", (code) => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err)
return console.error(
"Error while trying to retrieve access token",
err
);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log("Token stored to", TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}

/**
* Prints the names and majors of students in a sample spreadsheet:
* @see https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
* @param {google.auth.OAuth2} auth The authenticated Google OAuth client.
*/
function listMajors(auth) {
const sheets = google.sheets({ version: "v4", auth });
sheets.spreadsheets.values.get(
{
spreadsheetId: "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms",
range: "Class Data!A2:E",
},
(err, res) => {
if (err) return console.log("The API returned an error: " + err);
const rows = res.data.values;
if (rows.length) {
console.log("Name, Major:");
// Print columns A and E, which correspond to indices 0 and 4.
rows.map((row) => {
console.log(`${row[0]}, ${row[4]}`);
});
} else {
console.log("No data found.");
}
}
);
}
57 changes: 57 additions & 0 deletions src/site/_data/prod/read_sheet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const { google } = require("googleapis");
const sheets = google.sheets("v4");

async function main() {
const authClient = await authorize();
const request = {
// The ID of the spreadsheet to retrieve data from.
spreadsheetId: "1I_CCul8qdZsiMkhFVguxmfurkviqx9uI6WitinPxUt4",

// The A1 notation of the values to retrieve.
ranges: ["A1:D500"], // TODO: Update placeholder value.

// How values should be represented in the output.
// The default render option is ValueRenderOption.FORMATTED_VALUE.
valueRenderOption: "", // TODO: Update placeholder value.

// How dates, times, and durations should be represented in the output.
// This is ignored if value_render_option is
// FORMATTED_VALUE.
// The default dateTime render option is [DateTimeRenderOption.SERIAL_NUMBER].
dateTimeRenderOption: "", // TODO: Update placeholder value.

auth: authClient,
};

try {
const response = (await sheets.spreadsheets.values.batchGet(request)).data;
// TODO: Change code below to process the `response` object:
console.log(JSON.stringify(response, null, 2));
} catch (err) {
console.error(err);
}
}
main();

async function authorize() {
// TODO: Change placeholder below to generate authentication credentials. See
// https://developers.google.com/sheets/quickstart/nodejs#step_3_set_up_the_sample
//
// Authorize using one of the following scopes:
// 'https://www.googleapis.com/auth/drive'
// 'https://www.googleapis.com/auth/drive.file'
// 'https://www.googleapis.com/auth/drive.readonly'
// 'https://www.googleapis.com/auth/spreadsheets'
// 'https://www.googleapis.com/auth/spreadsheets.readonly'
const SCOPES = ["https://www.googleapis.com/auth/spreadsheets.readonly"];
const TOKEN_PATH = "token.json";

let authClient =
"-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC40MYRAQ94TmbA\n0ICe4h92NlmNvCsKzJAqS/S4jXZFXylg57myNc36SB7jH/HvuE8wMM3GA5YaxDoh\nVN8jPvX7YYyS14IdbCDu4uLYCR/hVahNOPRiMlaOzE2RJQ2+RpHvGQ1XSK/Y3S1u\nHIHQgr1K3dLrn2ds31BzJSrvjbGHq2yZaXOrR0qq43K05Z8yXBRZzP0P7LvNGump\nCB0cbEXPP2USTitpcD3NnNFxhqNpscb134kRjhdc+/V9HUS6ITlQQjVDTfbrBNEs\nDFP6CmWTeyP9oDRF+vFg25mRtvbZslg0QUqpCAq9tzdIAV96RPmh6WhkJttapxw7\nD8pZlcIjAgMBAAECggEAP6aPgI238Tw3QVLN6WqBYWoof5r9y/NV92s/dkwqHow+\nqQRFvS2wqfEqyhhXb7Mveq5kQD099iv8xTwAuZfWieQ30N7uDgoOcZesfrDtzOJ+\nW1IxQJyLmRSd5k43pH+ThSBAqv36qhrKqbChuNk+LkmlecbljOaAQ5faaLSJHusC\nXlcw+Irp7U2iUZYEel9I7nNlYsceVjvUne1ja9xL8hYWpScclYczzOpOo2g0Nyxb\nG0YybAgGsbf3bY9FsVtVvVJkc89B4SV72TqYiNqWiIcfEkKnkwoBlbLj6Nb9ySSe\nuOT/bOoLokqY5hxhGsTVM8dqi6EwllWUOwXTEVJviQKBgQDcNrYQbXW1fo5m2soJ\nRRCYZXd8xq3VWvncyydpeYgJCJtdWK2+eOh1V+XnS04EdY3B4/cEKS8nQh975fB7\nL1F4M3kSSePvopVjhbYGoTWI/o1mL8Hi4HVMj8j9KP2uz+R1iQ//Ymkn3dKg2pUR\nduAWsU/ktgwVvRCbwlON/5NFRwKBgQDW2W8DvrXYogKjw5n3/D8MyIQkJzbKE1S0\nD8s0ZiiNacLFH0mjv4YrM6s8yk64KaJmgHdugTL08IOb3Cvx8lRdIBiW/Tp2s7nx\n+uAQiZnD9+Q1FWH9LKh3zb597MSvMTC7fNdNlzM7s4JUboUkKN5kvfB4PzG8rBHZ\n1AyMHj46RQKBgBG0YFzfwAfwfdhtHLM0F0p5Ver1OkKeBtqmhqunNrWrOHp/x7A5\nnk7Y20YGOuaG4PfGsTRnb0ATw949NWFiA4XLdZ9vy2CXzLTsqh7MVTaHaKzfiBIK\ng8O9B6a65fJpCnAcremVaujmn6mJCVUXHpsUdFzp+fzBb5VmQTt4Ycm/AoGABWjA\nBMYeae/aRSk9jSLKq5W4zfg2xuuprEbhhNY1mynYf4IEJp1B0YChhQxK4xQZRJ9j\nYmLaV5Rem+P1L0g8m4OdWt/RQv/PZKo+TexI9Mge9L8vEmK3cxy4+Q6m/QouAepo\nuUlfPteMJngJ3hkxUDQAA+cDZ46lfGh8UGLKikkCgYAroYl8GmeVrIOALlqqoaSz\nFD3TN0vyO+8mNvsbMc4RxQa0qfVoECrQle3TQAkys0XH3K1R2wx/lDeLNAFbvoCz\nQJ7op1zV9LVZbky4jGJFphX8WNjTo/bz+MJ73YwFi7VEd2B6KrFikWa7r/caxF/l\njRWdP4HbyKe/ayWTHp+lAw==\n-----END PRIVATE KEY-----\n";

if (authClient == null) {
throw Error("authentication failed");
}

return authClient;
}
47 changes: 0 additions & 47 deletions src/site/_data/prod/sheet.js

This file was deleted.

4 changes: 2 additions & 2 deletions src/site/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ This project could work as a *journal, quote collection, bookmark, or microblog*



{%- for type, arr in sheet -%}
{%- for type, arr in airtable_source -%}
<h3>{{ type | capitalize }}</h3>

<ul class="listing">
{% if type =='Link' %}
{%- for item in sheet.Link | reverse -%}
{%- for item in airtable_source.Link | reverse -%}
<li><a href={{item.message}} target="_blank">{{ item.message }} </a> <span> - {{ item.time }}<span> </li>
{%- endfor -%}
{% endif %}
Expand Down
Loading