This commit is contained in:
tree 2022-01-14 17:56:42 +01:00
rodič f333e6cedf
revize ad239d97e0
8 změnil soubory, kde provedl 354 přidání a 278 odebrání

Zobrazit soubor

@ -8,6 +8,9 @@ all: test build
test: test:
deno test --unstable --allow-read utils/test.js deno test --unstable --allow-read utils/test.js
format:
deno fmt utils/*.js README.md
build: build:
deno run --unstable --allow-read --allow-write utils/build.js deno run --unstable --allow-read --allow-write utils/build.js

Zobrazit soubor

@ -1,4 +1,3 @@
``` ```
██╗░░░██╗████████╗██╗░░██╗░█████╗░ ██╗░░░██╗████████╗██╗░░██╗░█████╗░
██║░░░██║╚══██╔══╝╚██╗██╔╝██╔══██╗ ██║░░░██║╚══██╔══╝╚██╗██╔╝██╔══██╗
@ -7,55 +6,64 @@
╚██████╔╝░░░██║░░░██╔╝╚██╗╚█████╔╝ ╚██████╔╝░░░██║░░░██╔╝╚██╗╚█████╔╝
░╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚════╝░ ░╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚════╝░
``` ```
> Otevřená komunitní kryptoměnová konference > Otevřená komunitní kryptoměnová konference
[![Test, build, deploy](https://github.com/gweicz/utxo/actions/workflows/deploy.yml/badge.svg)](https://github.com/gweicz/utxo/actions/workflows/deploy.yml) [![Test, build, deploy](https://github.com/gweicz/utxo/actions/workflows/deploy.yml/badge.svg)](https://github.com/gweicz/utxo/actions/workflows/deploy.yml)
Tento repozitář obsahuje základní specifikace (datové zdroje) všech ročníků konference. Tento repozitář obsahuje základní specifikace (datové zdroje) všech ročníků
konference.
Veškeré informace o konferenci naleznete na [docs.utxo.cz](https://docs.utxo.cz). Veškeré informace o konferenci naleznete na
[docs.utxo.cz](https://docs.utxo.cz).
## Specifikace ## Specifikace
* Zdrojové soubory ve formátu [YAML](https://yaml.org/) jsou umístěny v adresáři [`spec`](./spec). - Zdrojové soubory ve formátu [YAML](https://yaml.org/) jsou umístěny v adresáři
* Validační schéma ([JSON Schema](https://json-schema.org/)) najdete v adresáři [`utils/schema`](./utils/schema) [`spec`](./spec).
- Validační schéma ([JSON Schema](https://json-schema.org/)) najdete v adresáři
[`utils/schema`](./utils/schema)
Jako runtime se využívá Javascriptové [Deno](https://deno.land/). Jako runtime se využívá Javascriptové [Deno](https://deno.land/).
## Ročníky ## Ročníky
| Ročník | Název | Datum konání | Místo |
| --- | --- | --- | --- |
| 2022 | **UTXO.22** | 4.-5.6.2022 | Gabriel Loci, Praha |
| Ročník | Název | Datum konání | Místo |
| ------ | ----------- | ------------ | ------------------- |
| 2022 | **UTXO.22** | 4.-5.6.2022 | Gabriel Loci, Praha |
## HTTP Endpoint ## HTTP Endpoint
Veřejný HTTP endpoint s datovými soubory ve formátu JSON naleznete na adrese:
Veřejný HTTP endpoint s datovými soubory ve formátu JSON naleznete na adrese:
- [https://spec.utxo.cz/](https://spec.utxo.cz/) - [https://spec.utxo.cz/](https://spec.utxo.cz/)
## Datové sady ## Datové sady
| | Popis | Ročník 2022 |
| --- | --- | --- | | | Popis | Ročník 2022 |
| **index** | Základní údaje o ročníku | [https://spec.utxo.cz/22/](https://spec.utxo.cz/22/) | | ------------ | ------------------------------------------- | ------------------------------------------------------------------------------ |
| **speakers** | Přednášející | [https://spec.utxo.cz/22/speakers.json](https://spec.utxo.cz/22/speakers.json) | | **index** | Základní údaje o ročníku | [https://spec.utxo.cz/22/](https://spec.utxo.cz/22/) |
| **tracks** | Programové sekce | [https://spec.utxo.cz/22/tracks.json](https://spec.utxo.cz/22/tracks.json) | | **speakers** | Přednášející | [https://spec.utxo.cz/22/speakers.json](https://spec.utxo.cz/22/speakers.json) |
| **events** | Události | [https://spec.utxo.cz/22/events.json](https://spec.utxo.cz/22/events.json) | | **tracks** | Programové sekce | [https://spec.utxo.cz/22/tracks.json](https://spec.utxo.cz/22/tracks.json) |
| **faqs** | Často kladené dotazy (FAQ) | [https://spec.utxo.cz/22/faqs.json](https://spec.utxo.cz/22/faqs.json) | | **events** | Události | [https://spec.utxo.cz/22/events.json](https://spec.utxo.cz/22/events.json) |
| **faqs** | Často kladené dotazy (FAQ) | [https://spec.utxo.cz/22/faqs.json](https://spec.utxo.cz/22/faqs.json) |
| **partners** | Partneři (sponzoři, mediální partneři atp.) | [https://spec.utxo.cz/22/partners.json](https://spec.utxo.cz/22/partners.json) | | **partners** | Partneři (sponzoři, mediální partneři atp.) | [https://spec.utxo.cz/22/partners.json](https://spec.utxo.cz/22/partners.json) |
| **bundle** | Vše v jednom souboru | [https://spec.utxo.cz/22/bundle.json](https://spec.utxo.cz/22/bundle.json) | | **bundle** | Vše v jednom souboru | [https://spec.utxo.cz/22/bundle.json](https://spec.utxo.cz/22/bundle.json) |
## Detaily k jednotlivým ročníkům ## Detaily k jednotlivým ročníkům
### UTXO.22 ### UTXO.22
> 4.-5. června 2022, Gabriel Loci (Praha) > 4.-5. června 2022, Gabriel Loci (Praha)
#### Související repozitáře #### Související repozitáře
| Repozitář | Popis | | Repozitář | Popis |
| --- | --- | | ----------------------------------------------------------------- | ------------------------------- |
| [gweicz/utxo22-docs](https://github.com/gweicz/utxo22-docs) | GitBook dokumentace | | [gweicz/utxo22-docs](https://github.com/gweicz/utxo22-docs) | GitBook dokumentace |
| [gweicz/utxo22-landing](https://github.com/gweicz/utxo22-landing) | Dočasná landing page na utxo.cz | | [gweicz/utxo22-landing](https://github.com/gweicz/utxo22-landing) | Dočasná landing page na utxo.cz |
## Kontakt ## Kontakt
* Web: [utxo.cz](https://utxo.cz)
* Dokumentace: [docs.utxo.cz](https://docs.utxo.cz) - Web: [utxo.cz](https://utxo.cz)
- Dokumentace: [docs.utxo.cz](https://docs.utxo.cz)

Zobrazit soubor

@ -1,7 +1,6 @@
import { UTXOEngine } from "./engine.js" import { UTXOEngine } from "./engine.js";
const utxo = new UTXOEngine({ srcDir: './spec' }) const utxo = new UTXOEngine({ srcDir: "./spec" });
await utxo.init() await utxo.init();
await utxo.build('./dist')
await utxo.build("./dist");

Zobrazit soubor

@ -1,8 +1,8 @@
import { emptyDir, exists } from 'https://deno.land/std@0.119.0/fs/mod.ts' import { emptyDir, exists } from "https://deno.land/std@0.119.0/fs/mod.ts";
import { copy } from 'https://deno.land/std@0.119.0/fs/copy.ts' import { copy } from "https://deno.land/std@0.119.0/fs/copy.ts";
import { load } from 'https://deno.land/x/js_yaml_port@3.14.0/js-yaml.js' import { load } from "https://deno.land/x/js_yaml_port@3.14.0/js-yaml.js";
const baseUrl = 'https://spec.utxo.cz' const baseUrl = "https://spec.utxo.cz";
const banner = ` const banner = `
@ -11,157 +11,181 @@ const banner = `
` `;
export class UTXOEngine { export class UTXOEngine {
constructor (options = {}) { constructor(options = {}) {
this.options = options this.options = options;
this.srcDir = this.options.srcDir || './spec' this.srcDir = this.options.srcDir || "./spec";
if (!this.options.silent) { if (!this.options.silent) {
console.log(banner) console.log(banner);
} }
this.imageTypes = [ this.imageTypes = [
['web', 'png'], ["web", "png"],
['web', 'webp'], ["web", "webp"],
['web', 'jpg'], ["web", "jpg"],
['sm', 'png'], ["sm", "png"],
['sm', 'webp'], ["sm", "webp"],
['twitter', 'jpg'] ["twitter", "jpg"],
] ];
} }
async init () { async init() {
this.entries = {} this.entries = {};
for await (const f of Deno.readDir(this.srcDir)) { for await (const f of Deno.readDir(this.srcDir)) {
if (!f.name.match(/^\d+$/)) { if (!f.name.match(/^\d+$/)) {
continue continue;
} }
const specDir = [this.srcDir, f.name].join('/') const specDir = [this.srcDir, f.name].join("/");
const entry = this.entries[f.name] = {} const entry = this.entries[f.name] = {};
// load index // load index
entry.index = await this._yamlLoad([specDir, 'index.yaml'].join('/')) entry.index = await this._yamlLoad([specDir, "index.yaml"].join("/"));
// load sub-specs // load sub-specs
entry.specs = {} entry.specs = {};
for (const sp of entry.index.specDef) { for (const sp of entry.index.specDef) {
entry.specs[sp.type] = await this._yamlLoad([specDir, `${sp.type}.yaml`].join('/')) entry.specs[sp.type] = await this._yamlLoad(
[specDir, `${sp.type}.yaml`].join("/"),
);
// post processing of sub-specs // post processing of sub-specs
switch (sp.type) { switch (sp.type) {
case 'speakers': case "speakers":
case 'partners': case "partners":
for (const s of entry.specs[sp.type]) { for (const s of entry.specs[sp.type]) {
if (!s.photos) { if (!s.photos) {
s.photos = [] s.photos = [];
} }
for (const [it, format] of this.imageTypes) { for (const [it, format] of this.imageTypes) {
if (await exists([this.srcDir, f.name, 'photos', sp.type, `${s.id}-${it}.${format}`].join('/'))) { if (
s.photos.push(`${it}:${format}`) await exists(
[
this.srcDir,
f.name,
"photos",
sp.type,
`${s.id}-${it}.${format}`,
].join("/"),
)
) {
s.photos.push(`${it}:${format}`);
} }
} }
} }
if (sp.type === 'speakers') { if (sp.type === "speakers") {
entry.specs[sp.type] = entry.specs[sp.type].sort((x, y) => x.name.localeCompare(y.name)) entry.specs[sp.type] = entry.specs[sp.type].sort((x, y) =>
x.name.localeCompare(y.name)
);
} }
break break;
} }
} }
} }
if (!this.options.silent) { if (!this.options.silent) {
console.log(`UTXO entries: [ ${Object.keys(this.entries).join(', ')} ]\n`) console.log(
`UTXO entries: [ ${Object.keys(this.entries).join(", ")} ]\n`,
);
} }
} }
entriesList () { entriesList() {
return Object.keys(this.entries) return Object.keys(this.entries);
} }
async build (outputDir) { async build(outputDir) {
await emptyDir(outputDir) await emptyDir(outputDir);
const entriesIndex = [] const entriesIndex = [];
for (const entryId of Object.keys(this.entries)) { for (const entryId of Object.keys(this.entries)) {
if (!this.options.silent) { if (!this.options.silent) {
console.log(`UTXO.${entryId}: building specs ..`) console.log(`UTXO.${entryId}: building specs ..`);
} }
const entry = this.entries[entryId] const entry = this.entries[entryId];
const entryDir = [outputDir, entryId].join('/') const entryDir = [outputDir, entryId].join("/");
await emptyDir(entryDir) await emptyDir(entryDir);
// write sub-specs // write sub-specs
const specEndpoints = {} const specEndpoints = {};
for (const specName of Object.keys(entry.specs)) { for (const specName of Object.keys(entry.specs)) {
await this._jsonWrite([entryDir, `${specName}.json`], entry.specs[specName]) await this._jsonWrite(
specEndpoints[specName] = `${baseUrl}/${entryId}/${specName}.json` [entryDir, `${specName}.json`],
entry.specs[specName],
);
specEndpoints[specName] = `${baseUrl}/${entryId}/${specName}.json`;
} }
// write index // write index
const index = JSON.parse(JSON.stringify(entry.index)) const index = JSON.parse(JSON.stringify(entry.index));
delete index.specDef delete index.specDef;
index.spec = specEndpoints index.spec = specEndpoints;
index.stats = { counts: {} } index.stats = { counts: {} };
for (const sc of Object.keys(entry.specs)) { for (const sc of Object.keys(entry.specs)) {
index.stats.counts[sc] = entry.specs[sc].length index.stats.counts[sc] = entry.specs[sc].length;
} }
index.time = new Date() index.time = new Date();
await this._jsonWrite([entryDir, 'index.json'], index) await this._jsonWrite([entryDir, "index.json"], index);
// write bundle // write bundle
const bundle = JSON.parse(JSON.stringify(index)) const bundle = JSON.parse(JSON.stringify(index));
bundle.spec = entry.specs bundle.spec = entry.specs;
await this._jsonWrite([entryDir, 'bundle.json'], bundle) await this._jsonWrite([entryDir, "bundle.json"], bundle);
// copy photos // copy photos
const outputPhotosDir = [entryDir, 'photos'].join('/') const outputPhotosDir = [entryDir, "photos"].join("/");
if (!this.options.silent) { if (!this.options.silent) {
console.log(`UTXO.${entryId}: copying photos ..`) console.log(`UTXO.${entryId}: copying photos ..`);
console.log(`copying photos to ${outputPhotosDir}`) console.log(`copying photos to ${outputPhotosDir}`);
} }
await copy([this.srcDir, entryId, 'photos'].join('/'), outputPhotosDir, { overwrite: true }) await copy([this.srcDir, entryId, "photos"].join("/"), outputPhotosDir, {
overwrite: true,
});
entriesIndex.push({ entriesIndex.push({
id: `utxo${entryId}`, id: `utxo${entryId}`,
entryId, entryId,
url: `${baseUrl}/${entryId}` url: `${baseUrl}/${entryId}`,
}) });
} }
// write global index // write global index
await this._jsonWrite([outputDir, 'index.json'], entriesIndex) await this._jsonWrite([outputDir, "index.json"], entriesIndex);
if (!this.options.silent) { if (!this.options.silent) {
console.log('\nBuild done') console.log("\nBuild done");
} }
} }
async schemas () { async schemas() {
const schemaDir = './utils/schema' const schemaDir = "./utils/schema";
const arr = [] const arr = [];
for await (const f of Deno.readDir(schemaDir)) { for await (const f of Deno.readDir(schemaDir)) {
const m = f.name.match(/^(.+)\.yaml$/) const m = f.name.match(/^(.+)\.yaml$/);
if (!m) { if (!m) {
continue continue;
} }
arr.push({ name: m[1], schema: await this._yamlLoad([schemaDir, f.name].join('/')) }) arr.push({
name: m[1],
schema: await this._yamlLoad([schemaDir, f.name].join("/")),
});
} }
return arr return arr;
} }
async _yamlLoad (fn) { async _yamlLoad(fn) {
return load(await Deno.readTextFile(fn)) return load(await Deno.readTextFile(fn));
} }
async _jsonWrite (fn, data) { async _jsonWrite(fn, data) {
if (Array.isArray(fn)) { if (Array.isArray(fn)) {
fn = fn.join('/') fn = fn.join("/");
} }
await Deno.writeTextFile(fn, JSON.stringify(data, null, 2)) await Deno.writeTextFile(fn, JSON.stringify(data, null, 2));
if (!this.options.silent) { if (!this.options.silent) {
console.log(`${fn} writed`) console.log(`${fn} writed`);
} }
return true return true;
} }
} }

Zobrazit soubor

@ -1,27 +1,30 @@
import { Table } from "https://deno.land/x/cliffy@v0.20.1/table/mod.ts" import { Table } from "https://deno.land/x/cliffy@v0.20.1/table/mod.ts";
import { UTXOEngine } from './engine.js' import { UTXOEngine } from "./engine.js";
const utxo = new UTXOEngine({ silent: true }) const utxo = new UTXOEngine({ silent: true });
await utxo.init() await utxo.init();
const entryId = '22' const entryId = "22";
const entry = utxo.entries[entryId] const entry = utxo.entries[entryId];
const tracksCount = {} const tracksCount = {};
for (const sp of entry.specs.speakers) { for (const sp of entry.specs.speakers) {
for (const tr of sp.tracks) { for (const tr of sp.tracks) {
if (!tracksCount[tr]) { if (!tracksCount[tr]) {
tracksCount[tr] = 0 tracksCount[tr] = 0;
} }
tracksCount[tr]++ tracksCount[tr]++;
} }
} }
const tracks = entry.specs.tracks.map(t => [t.id, '|' + '+'.repeat(tracksCount[t.id] || '0' ) ]) const tracks = entry.specs.tracks.map(
(t) => [t.id, "|" + "+".repeat(tracksCount[t.id] || "0")],
);
const table = Table.from(tracks) const table = Table.from(tracks);
//table.border(true) //table.border(true)
console.log('\nRozložení jednotlivých tématických sekcí dle přednášejících:\n' + '-'.repeat(60)) console.log(
console.log(table.toString() + '\n') "\nRozložení jednotlivých tématických sekcí dle přednášejících:\n" +
"-".repeat(60),
);
console.log(table.toString() + "\n");

Zobrazit soubor

@ -1,44 +1,42 @@
import { assertEquals } from "https://deno.land/std@0.119.0/testing/asserts.ts" import { assertEquals } from "https://deno.land/std@0.119.0/testing/asserts.ts";
import { UTXOEngine } from './engine.js' import { UTXOEngine } from "./engine.js";
// initialize ajv JSON Schema validator // initialize ajv JSON Schema validator
import Ajv from 'https://esm.sh/ajv@8.8.1?pin=v58' import Ajv from "https://esm.sh/ajv@8.8.1?pin=v58";
import addFormats from 'https://esm.sh/ajv-formats@2.1.1' import addFormats from "https://esm.sh/ajv-formats@2.1.1";
const ajv = new Ajv() const ajv = new Ajv();
addFormats(ajv) addFormats(ajv);
const utxo = new UTXOEngine({ silent: true }) const utxo = new UTXOEngine({ silent: true });
await utxo.init() await utxo.init();
const schemas = await utxo.schemas() const schemas = await utxo.schemas();
const validators = {} const validators = {};
for (const item of schemas) { for (const item of schemas) {
validators[item.name] = ajv.compile(item.schema) validators[item.name] = ajv.compile(item.schema);
} }
// check entries // check entries
for (const entryId of utxo.entriesList()) { for (const entryId of utxo.entriesList()) {
const entry = utxo.entries[entryId] const entry = utxo.entries[entryId];
// check index // check index
Deno.test(`UTXO.${entryId}: index.yaml`, () => { Deno.test(`UTXO.${entryId}: index.yaml`, () => {
if (!validators.index(entry.index)) { if (!validators.index(entry.index)) {
throw validators.index.errors throw validators.index.errors;
} }
}) });
// check specific specs // check specific specs
for (const specId of Object.keys(entry.specs)) { for (const specId of Object.keys(entry.specs)) {
Deno.test(`UTXO.${entryId}: ${specId}`, () => { Deno.test(`UTXO.${entryId}: ${specId}`, () => {
if (!validators[specId]) { if (!validators[specId]) {
return null return null;
} }
if (!validators[specId](entry.specs[specId])) { if (!validators[specId](entry.specs[specId])) {
throw validators[specId].errors throw validators[specId].errors;
} }
}) });
} }
} }

Zobrazit soubor

@ -1,94 +1,96 @@
import { config } from "https://deno.land/x/dotenv/mod.ts" import { config } from "https://deno.land/x/dotenv/mod.ts";
import SimpleTwitter from "https://deno.land/x/simple_twitter_deno@0.05/simple_twitter_deno.ts" import SimpleTwitter from "https://deno.land/x/simple_twitter_deno@0.05/simple_twitter_deno.ts";
import { Table } from "https://deno.land/x/cliffy@v0.20.1/table/mod.ts" import { Table } from "https://deno.land/x/cliffy@v0.20.1/table/mod.ts";
import { UTXOEngine } from './engine.js' import { UTXOEngine } from "./engine.js";
import { exists } from "https://deno.land/std/fs/mod.ts" import { exists } from "https://deno.land/std/fs/mod.ts";
import { fromStreamReader } from "https://deno.land/std@0.60.0/io/streams.ts" import { fromStreamReader } from "https://deno.land/std@0.60.0/io/streams.ts";
const utxo = new UTXOEngine({ silent: true }) const utxo = new UTXOEngine({ silent: true });
await utxo.init() await utxo.init();
config({ path: ".env", export: true }) config({ path: ".env", export: true });
const twitterImagesPath = './spec/22/photos/speakers/' const twitterImagesPath = "./spec/22/photos/speakers/";
const twitterPartnersImagesPath = './spec/22/photos/partners/' const twitterPartnersImagesPath = "./spec/22/photos/partners/";
const simple_twitter = new SimpleTwitter({ const simple_twitter = new SimpleTwitter({
consumer_key: Deno.env.get("CONSUMER_KEY"), consumer_key: Deno.env.get("CONSUMER_KEY"),
consumer_secret: Deno.env.get("CONSUMER_SECRET"), consumer_secret: Deno.env.get("CONSUMER_SECRET"),
access_token: Deno.env.get("ACCESS_TOKEN"), access_token: Deno.env.get("ACCESS_TOKEN"),
access_token_secret: Deno.env.get("ACCESS_TOKEN_SECRET"), access_token_secret: Deno.env.get("ACCESS_TOKEN_SECRET"),
bearer_token: Deno.env.get("BEARER_TOKEN") bearer_token: Deno.env.get("BEARER_TOKEN"),
}) });
const entryId = '22' const entryId = "22";
const entry = utxo.entries[entryId] const entry = utxo.entries[entryId];
const arr = [] const arr = [];
let total = 0 let total = 0;
let items = [];
// partners // partners
for (const sp of entry.specs.partners) { for (const sp of entry.specs.partners) {
if (!sp.twitter) { if (!sp.twitter) {
continue continue;
} }
const tw = await twitterUser(sp.twitter) const tw = await twitterUser(sp.twitter);
if (!tw) { if (!tw) {
continue continue;
} }
const imageFn = twitterPartnersImagesPath + sp.id + '-twitter.jpg' const imageFn = twitterPartnersImagesPath + sp.id + "-twitter.jpg";
if (!await exists(imageFn)) { if (!await exists(imageFn)) {
const url = tw.profile_image_url_https.replace('_normal', '') const url = tw.profile_image_url_https.replace("_normal", "");
console.log(url) console.log(url);
const res = await fetch(url) const res = await fetch(url);
const file = await Deno.open(imageFn, { create: true, write: true }) const file = await Deno.open(imageFn, { create: true, write: true });
const reader = fromStreamReader(res.body.getReader()) const reader = fromStreamReader(res.body.getReader());
await Deno.copy(reader, file) await Deno.copy(reader, file);
file.close() file.close();
} }
arr.push([ `partner:${sp.type}`, tw.screen_name, tw.followers_count ]) items.push([`partner:${sp.type}`, tw.screen_name, tw.followers_count]);
total += tw.followers_count total += tw.followers_count;
} }
// speakers // speakers
for (const sp of entry.specs.speakers) { for (const sp of entry.specs.speakers) {
if (!sp.twitter) { if (!sp.twitter) {
continue continue;
} }
const tw = await twitterUser(sp.twitter) const tw = await twitterUser(sp.twitter);
if (!tw) { if (!tw) {
continue continue;
} }
const imageFn = twitterImagesPath + sp.id + '-twitter.jpg' const imageFn = twitterImagesPath + sp.id + "-twitter.jpg";
if (!await exists(imageFn)) { if (!await exists(imageFn)) {
const url = tw.profile_image_url_https.replace('_normal', '') const url = tw.profile_image_url_https.replace("_normal", "");
console.log(url) console.log(url);
const res = await fetch(url) const res = await fetch(url);
const file = await Deno.open(imageFn, { create: true, write: true }) const file = await Deno.open(imageFn, { create: true, write: true });
const reader = fromStreamReader(res.body.getReader()) const reader = fromStreamReader(res.body.getReader());
await Deno.copy(reader, file) await Deno.copy(reader, file);
file.close() file.close();
} }
arr.push([ 'speaker', tw.screen_name, tw.followers_count ]) items.push(["speaker", tw.screen_name, Number(tw.followers_count)]);
total += tw.followers_count total += tw.followers_count;
} }
arr.push([]) arr.push(...items.sort((x, y) => x[2] < y[2] ? 1 : -1));
arr.push([ 'total', total ])
const table = Table.from(arr) arr.push([]);
console.log('\nTwitter followers count:\n\n' + table.toString() + '\n') arr.push(["total", "", total]);
const table = Table.from(arr);
console.log("\nTwitter followers count:\n\n" + table.toString() + "\n");
async function twitterUser(screen_name) { async function twitterUser(screen_name) {
const resp = await simple_twitter.get("users/lookup", { screen_name }) const resp = await simple_twitter.get("users/lookup", { screen_name });
if (resp.length === 1) { if (resp.length === 1) {
return resp[0] return resp[0];
} }
return null return null;
} }

Zobrazit soubor

@ -1,142 +1,181 @@
import { UTXOEngine } from "./engine.js" import { UTXOEngine } from "./engine.js";
import { markdownTable } from 'https://cdn.skypack.dev/markdown-table@3?dts' import { markdownTable } from "https://cdn.skypack.dev/markdown-table@3?dts";
const utxo = new UTXOEngine({ silent: true }) const utxo = new UTXOEngine({ silent: true });
await utxo.init() await utxo.init();
// get 2022 // get 2022
const entry = utxo.entries['22'] const entry = utxo.entries["22"];
// SPEAKERS // SPEAKERS
const speakers = entry.specs.speakers const speakers = entry.specs.speakers;
const sortedSpeakers = speakers.sort((a, b) => a.name.localeCompare(b.name)) const sortedSpeakers = speakers.sort((a, b) => a.name.localeCompare(b.name));
const tracks = entry.specs.tracks const tracks = entry.specs.tracks;
const methods = { const methods = {
// SPEAKERS - table // SPEAKERS - table
async speakersTableGen () { async speakersTableGen() {
const speakersTableArr = [["Jméno", "Organizace"]];
const speakersTableArr = [[ 'Jméno', 'Organizace' ]]
for (const speaker of sortedSpeakers) { for (const speaker of sortedSpeakers) {
const name = `**${speaker.name}**` const name = `**${speaker.name}**`;
speakersTableArr.push([ speakersTableArr.push([
(speaker.twitter ? `[${name}](https://twitter.com/${speaker.twitter})` : name) + (speaker.nickname ? ` (${speaker.nickname})` : ''), (speaker.twitter
speaker.orgs ? speaker.orgs.trim() : '' ? `[${name}](https://twitter.com/${speaker.twitter})`
]) : name) + (speaker.nickname ? ` (${speaker.nickname})` : ""),
speaker.orgs ? speaker.orgs.trim() : "",
]);
} }
const speakersTable = `Celkem přednášejících: **${speakers.length}**\n\n_(abecedně)_\n\n` + markdownTable(speakersTableArr) const speakersTable =
`Celkem přednášejících: **${speakers.length}**\n\n_(abecedně)_\n\n` +
markdownTable(speakersTableArr);
//console.log(speakersTable) //console.log(speakersTable)
return speakersTable return speakersTable;
}, },
// SPEAKERS - leads // SPEAKERS - leads
async speakersLeadsGen () { async speakersLeadsGen() {
const speakersLeadsArr = [];
const speakersLeadsArr = [] for (const speaker of sortedSpeakers.filter((speaker) => speaker.lead)) {
for (const speaker of sortedSpeakers.filter(speaker => speaker.lead)) { const orgs = speaker.orgs ? `\n* ${speaker.orgs.trim("\n")}` : "";
const orgs = speaker.orgs ? `\n* ${speaker.orgs.trim('\n')}` : '' const socials = [];
const socials = []
if (speaker.twitter) { if (speaker.twitter) {
socials.push(`Twitter: [@${speaker.twitter}](https://twitter.com/${speaker.twitter})`) socials.push(
`Twitter: [@${speaker.twitter}](https://twitter.com/${speaker.twitter})`,
);
} }
if (speaker.web) { if (speaker.web) {
socials.push(`Web: [${speaker.web.name ? speaker.web.name : speaker.name}](${speaker.web.url})`) socials.push(
`Web: [${
speaker.web.name ? speaker.web.name : speaker.name
}](${speaker.web.url})`,
);
} }
const img = `![](https://spec.utxo.cz/22/photos/speakers/${speaker.id}-sm.png)` const img =
const item = `### ${img} ${speaker.name}\n\n* ${speaker.bio.trim()}${orgs}\n* ${socials.join(', ')}`; `![](https://spec.utxo.cz/22/photos/speakers/${speaker.id}-sm.png)`;
speakersLeadsArr.push(item) const item =
`### ${img} ${speaker.name}\n\n* ${speaker.bio.trim()}${orgs}\n* ${
socials.join(", ")
}`;
speakersLeadsArr.push(item);
} }
const speakersLeads = `_(abecedně)_\n\n` + speakersLeadsArr.join('\n\n') const speakersLeads = `_(abecedně)_\n\n` + speakersLeadsArr.join("\n\n");
//console.log(speakersLeads) //console.log(speakersLeads)
return speakersLeads return speakersLeads;
}, },
// SPEAKERS - write file // SPEAKERS - write file
async speakersBuild () { async speakersBuild() {
const speakersDocFile = './docs/prednasejici.md' const speakersDocFile = "./docs/prednasejici.md";
const speakersText = await Deno.readTextFile(speakersDocFile) const speakersText = await Deno.readTextFile(speakersDocFile);
let output = speakersText let output = speakersText;
output = output.replace(/## Významní hosté([\s\S]+)## Seznam/m, `## Významní hosté\n\n${await methods.speakersLeadsGen()}\n\n## Seznam`) output = output.replace(
output = output.replace(/## Seznam všech přednášejících([\s\S]+)### Datový/m, `## Seznam všech přednášejících\n\n${await methods.speakersTableGen()}\n\n### Datový`) /## Významní hosté([\s\S]+)## Seznam/m,
await Deno.writeTextFile(speakersDocFile, output) `## Významní hosté\n\n${await methods.speakersLeadsGen()}\n\n## Seznam`,
);
output = output.replace(
/## Seznam všech přednášejících([\s\S]+)### Datový/m,
`## Seznam všech přednášejících\n\n${await methods
.speakersTableGen()}\n\n### Datový`,
);
await Deno.writeTextFile(speakersDocFile, output);
}, },
// TRACKS // TRACKS
async tracksGen () { async tracksGen() {
const output = [];
const output = []
for (const track of tracks) { for (const track of tracks) {
output.push(`<details>\n\n<summary>${track.name}</summary>\n\n${track.examples.trim()}\n\n</details>`) output.push(
`<details>\n\n<summary>${track.name}</summary>\n\n${track.examples.trim()}\n\n</details>`,
);
} }
return `Přednášky a workshopy budou rozděleny do **${tracks.length} tématických programových sekcí**. Níže naleznete jejich přehled a relevantní příklady.\n\n` + output.join('\n\n') return `Přednášky a workshopy budou rozděleny do **${tracks.length} tématických programových sekcí**. Níže naleznete jejich přehled a relevantní příklady.\n\n` +
output.join("\n\n");
}, },
async tracksBuild () { async tracksBuild() {
const sourceFile = './docs/hlavni-program.md' const sourceFile = "./docs/hlavni-program.md";
const sourceText = await Deno.readTextFile(sourceFile) const sourceText = await Deno.readTextFile(sourceFile);
let output = sourceText let output = sourceText;
output = output.replace(/## Programové sekce([\s\S]+)## Časová/m, `## Programové sekce\n\n${await methods.tracksGen()}\n\n## Časová`) output = output.replace(
await Deno.writeTextFile(sourceFile, output) /## Programové sekce([\s\S]+)## Časová/m,
`## Programové sekce\n\n${await methods.tracksGen()}\n\n## Časová`,
);
await Deno.writeTextFile(sourceFile, output);
}, },
// FAQs // FAQs
async faqsGen () { async faqsGen() {
const output = [] const output = [];
for (const item of entry.specs.faqs) { for (const item of entry.specs.faqs) {
output.push(`<details>\n\n<summary>${item.question.trim()}</summary>\n\n${item.answer.trim()}\n\n</details>`) output.push(
`<details>\n\n<summary>${item.question.trim()}</summary>\n\n${item.answer.trim()}\n\n</details>`,
);
} }
return output.join("\n\n") return output.join("\n\n");
}, },
async faqsBuild () { async faqsBuild() {
const docFile = './docs/faq.md' const docFile = "./docs/faq.md";
const docText = await Deno.readTextFile(docFile) const docText = await Deno.readTextFile(docFile);
const faqs = await this.faqsGen() const faqs = await this.faqsGen();
let output = docText let output = docText;
output = output.replace(/# FAQ[\s\S]+/m, `# FAQ\n\n${faqs}\n`) output = output.replace(/# FAQ[\s\S]+/m, `# FAQ\n\n${faqs}\n`);
// TODO replace // TODO replace
await Deno.writeTextFile(docFile, output) await Deno.writeTextFile(docFile, output);
}, },
// PARTNERS // PARTNERS
async partnersGen (type = 'community') { async partnersGen(type = "community") {
const arr = [[ 'Název', 'Popis' ]] const arr = [["Název", "Popis"]];
for (const item of entry.specs.partners.filter(p => p.type === type)) { for (const item of entry.specs.partners.filter((p) => p.type === type)) {
arr.push([ `[**${item.name}**](${item.twitter ? 'https://twitter.com/'+item.twitter : item.web?.url})`, item.desc ]) arr.push([
`[**${item.name}**](${
item.twitter ? "https://twitter.com/" + item.twitter : item.web?.url
})`,
item.desc,
]);
} }
const table = markdownTable(arr) const table = markdownTable(arr);
return table return table;
}, },
async partnersBuild () { async partnersBuild() {
const docFile = './docs/partneri.md' const docFile = "./docs/partneri.md";
const docText = await Deno.readTextFile(docFile) const docText = await Deno.readTextFile(docFile);
let output = docText let output = docText;
output = output.replace(/## Spolupracující komunity([\s\S]+)## Mediální/m, `## Spolupracující komunity\n\n${await methods.partnersGen('community')}\n\n## Mediální`) output = output.replace(
output = output.replace(/## Mediální partneři([\s\S]+)/m, `## Mediální partneři\n\n${await methods.partnersGen('medium')}\n\n`) /## Spolupracující komunity([\s\S]+)## Mediální/m,
await Deno.writeTextFile(docFile, output) `## Spolupracující komunity\n\n${await methods.partnersGen(
"community",
)}\n\n## Mediální`,
);
output = output.replace(
/## Mediální partneři([\s\S]+)/m,
`## Mediální partneři\n\n${await methods.partnersGen("medium")}\n\n`,
);
await Deno.writeTextFile(docFile, output);
const docFile2 = './docs/sponzori.md' const docFile2 = "./docs/sponzori.md";
const docText2 = await Deno.readTextFile(docFile2) const docText2 = await Deno.readTextFile(docFile2);
let output2 = docText2 let output2 = docText2;
output2 = output2.replace(/## Seznam sponzorů([\s\S]+)/m, `## Seznam sponzorů\n\n${await methods.partnersGen('sponsor')}\n\n`) output2 = output2.replace(
await Deno.writeTextFile(docFile2, output2) /## Seznam sponzorů([\s\S]+)/m,
} `## Seznam sponzorů\n\n${await methods.partnersGen("sponsor")}\n\n`,
} );
await Deno.writeTextFile(docFile2, output2);
},
};
if (!Deno.args[0]) { if (!Deno.args[0]) {
await methods.speakersBuild() await methods.speakersBuild();
await methods.tracksBuild() await methods.tracksBuild();
await methods.faqsBuild() await methods.faqsBuild();
await methods.partnersBuild() await methods.partnersBuild();
console.log('done') console.log("done");
} else { } else {
console.log(await methods[Deno.args[0]](Deno.args[1])) console.log(await methods[Deno.args[0]](Deno.args[1]));
} }