Skip to content

Instantly share code, notes, and snippets.

@bouzuya
Last active May 21, 2020 13:42
Show Gist options
  • Save bouzuya/661d1922ca6e6134d853a087e0ee58eb to your computer and use it in GitHub Desktop.
Save bouzuya/661d1922ca6e6134d853a087e0ee58eb to your computer and use it in GitHub Desktop.
bbn-furikaeri

bbn-furikaeri

Example

$ bbn-furikaeri
2020-05-20 ABC067 を解いた等
https://blog.bouzuya.net/2020/05/20/

2019-05-21 健康診断など
https://blog.bouzuya.net/2019/05/21/

2018-05-21 bouzuya/purescript-bouzuya-http-method & http-status-code をつくった
https://blog.bouzuya.net/2018/05/21/

2017-05-21 2017-W20 ふりかえり
https://blog.bouzuya.net/2017/05/21/

2016-05-21 京都 Clojure の集い 16.05 にでた
https://blog.bouzuya.net/2016/05/21/

2015-05-22 bouzuya/kraken のリファクタリング
https://blog.bouzuya.net/2015/05/22/

Installation

$ deno --version
deno 1.0.1
v8 8.4.300
typescript 3.9.2
$ # bbn-furikaeri

Example

$ bbn-furikaeri
2020-05-20 ABC067 を解いた等
https://blog.bouzuya.net/2020/05/20/

2019-05-21 健康診断など
https://blog.bouzuya.net/2019/05/21/

2018-05-21 bouzuya/purescript-bouzuya-http-method & http-status-code をつくった
https://blog.bouzuya.net/2018/05/21/

2017-05-21 2017-W20 ふりかえり
https://blog.bouzuya.net/2017/05/21/

2016-05-21 京都 Clojure の集い 16.05 にでた
https://blog.bouzuya.net/2016/05/21/

2015-05-22 bouzuya/kraken のリファクタリング
https://blog.bouzuya.net/2015/05/22/

Installation

$ deno --version
deno 1.0.1
v8 8.4.300
typescript 3.9.2
$ deno install --allow-env --allow-read --name bbn-furikaeri https://gist.githubusercontent.com/bouzuya/661d1922ca6e6134d853a087e0ee58eb/raw/8bb03b62aa053f1fe6442c337926944bae033b17/main.ts
import { main } from "./mod.ts";
main();
import {
assertEquals,
assertThrows,
} from "https://deno.land/[email protected]/testing/asserts.ts";
import { parse } from "https://deno.land/[email protected]/flags/mod.ts";
import * as fs from "https://deno.land/[email protected]/node/fs.ts";
import * as path from "https://deno.land/[email protected]/node/path.ts";
type DateString = string; // YYYY-MM-DD
function range(n: number): Array<number> {
if (n < 0) throw new Error("n < 0");
return new Array(n).fill(0).map((_, i) => i);
}
Deno.test("range", async () => {
assertThrows(() => range(-1));
assertEquals(range(0), []);
assertEquals(range(5), [0, 1, 2, 3, 4]);
});
function toDateString(d: Date): DateString {
return d.toISOString().substring(0, "YYYY-MM-DD".length);
}
Deno.test("toDateString", async () => {
assertEquals(toDateString(new Date("2020-05-20")), "2020-05-20");
});
function dateStringArray(today: DateString, count: number): Array<DateString> {
const oneYearInMs = 365 * 24 * 60 * 60 * 1000;
const d = new Date(today).getTime();
return range(count + 1).map((i) =>
toDateString(new Date(d - i * oneYearInMs))
);
}
Deno.test("dateStringArray", async () => {
assertEquals(dateStringArray("2020-05-20", 0), ["2020-05-20"]);
// 2020 is leap year
assertEquals(dateStringArray("2020-05-20", 1), ["2020-05-20", "2019-05-21"]);
assertEquals(
dateStringArray("2020-05-20", 2),
["2020-05-20", "2019-05-21", "2018-05-21"],
);
assertEquals(
dateStringArray("2019-05-20", 2),
["2019-05-20", "2018-05-20", "2017-05-20"],
);
});
function parseArgs(
def: { count: number; date: DateString; dir: string },
args: string[],
): { count: number; date: DateString; dir: string } {
const flags = parse(args, { string: ["count", "date", "dir"] });
const countString: string = flags.count ?? String(def.count);
const count = Number.parseInt(countString, 10);
if (Number.isNaN(count)) throw new Error("count is invalid");
const date: string = flags.date ?? def.date;
if (new Date(date).toString() === "Invalid Date") {
throw new Error("date is invalid");
}
const dir: string = flags.dir ?? def.dir;
if (dir.length === 0) {
throw new Error("dir is empty");
}
return { count, date, dir };
}
Deno.test("parseArgs", () => {
const d = {
"count": 5,
"date": "2020-05-20",
"dir": "/Users/bouzuya/bbn-data",
};
assertEquals(parseArgs(d, []), d);
assertThrows(() => parseArgs(d, ["--count"]));
assertThrows(() => parseArgs(d, ["--count", "abc"]));
assertEquals(parseArgs(d, ["--count", "1"]), { ...d, count: 1 });
assertThrows(() => parseArgs(d, ["--date"]));
assertThrows(() => parseArgs(d, ["--date", "abc"]));
assertThrows(() => parseArgs(d, ["--date", "2019-25-29"]));
assertEquals(
parseArgs(d, ["--date", "2020-05-21"]),
{ ...d, date: "2020-05-21" },
);
assertThrows(() => parseArgs(d, ["--dir"]));
assertEquals(parseArgs(d, ["--dir", "dir1"]), { ...d, dir: "dir1" });
});
export function main(): void {
const home = Deno.env.get("HOME");
if (typeof home === "undefined") throw new Error("HOME is not defined");
const { count, date, dir } = parseArgs(
{
count: 5,
date: toDateString(new Date()),
dir: path.join(home, "bbn-data"),
},
Deno.args,
);
for (const d of dateStringArray(date, count)) {
const [y, m, _] = d.split("-");
const p = path.join(dir, y, m, d + ".json");
const readTitle = () => {
try {
const data = fs.readFileSync(p, { encoding: "utf8" }) as string;
return JSON.parse(data).title;
} catch (_) {
return null;
}
};
const title = readTitle();
const url = "https://blog.bouzuya.net/" + d.split("-").join("/") + "/";
console.log(`${d} ${title}\n${url}\n`);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment