scripts: Add scripts to help testing and administration

This commit is contained in:
Alexander Polynomdivision 2018-10-01 17:08:37 +02:00
parent 4f133c55d2
commit 9144676ec2
4 changed files with 330 additions and 0 deletions

26
scripts/README.md Normal file
View File

@ -0,0 +1,26 @@
# Scripts
A few scripts to help with any task
## csv_vocab_to_mongo.py
Parses the vocabulary files in `$REPO_ROOT/data/vocab/`, converts the vocabulary items
into a format that fits the database model for vocabulary items (see `backend/db.md**) and
writes the data into the MongoDB database.
**NOTE**: Requires `pymongo` to be installed via pip
### Usage
`python csv_vocab_to_mongo.py <URI> <Database>`
- `URI`: The URI of the MongoDB instance
- `Database`: The name of the database in the MongoDB instance
## add_user.js
Asks the user about his data (username, password, class** and adds the user to the database.
**NOTE**: Requires `mongodb` to be installed via npm
### Usage
`node add_user.js <URI> <Database>`
- `URI`: The URI of the MongoDB instance
- `Database`: The name of the database in the MongoDB instance

78
scripts/add_user.js Normal file
View File

@ -0,0 +1,78 @@
const crypto = require("crypto");
const readline = require("readline");
const process = require("process");
const MongoClient = require("mongodb").MongoClient;
if (process.argv.length < 4) {
console.log("Not enough arguments");
process.exit(1);
}
function log(msg) {
console.log("[*]", msg);
}
(async () => {
const client = await (new MongoClient(process.argv[2])).connect();
const db = client.db(process.argv[3]);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question("Username? > ", username => {
rl.question("Class ID? > ", classId => {
rl.question("Password? > ", password => {
rl.question("Password (repeat)? > ", async (repeat) => {
if (repeat !== password) {
console.log(`Passwords for user ${username} don't match`);
rl.close();
} else {
// Generate a salt
log("Hashing password");
const salt = crypto.randomBytes(20).toString("hex");
const hash = crypto.pbkdf2Sync(password, salt, 50000, 512, "sha512").toString("hex");
// console.log(`Username: ${username}`);
// console.log(`Salt: ${salt}`);
// console.log(`Hash: ${hash}`);
const user = {
username,
salt,
hash,
// TODO: Fix this
classId,
// END TODO
score: 0,
showWelcome: true,
uid: 1,
lastReview: {
correct: 0,
wrong: 0,
},
lastLevel: 0,
levels: [],
vocabMetadata: {},
};
log("Writing to database...");
try {
await db.collection("users").insertOne(user);
} catch (err) {
log("Error while writing to database");
log(err);
}
rl.close();
process.exit(0);
}
});
});
});
});
})();

View File

@ -0,0 +1,147 @@
import csv
import sys
import os
import pymongo
# Definitions
TYPE_NOUNS = 0
TYPE_VERBS = 1
TYPE_ADJECTIVES = 2
PATH_TO_VOCAB = "../data/vocab"
def preprocess_row(row):
return row[1:]
def genus_to_datatype(gen):
if (gen == "m"): return "Maskulin"
if (gen == "w"): return "Feminin"
if (gen == "n"): return "Neutrum"
def log(msg, err=False, tabs=0):
if (not err):
print("[*] " + "\t" * tabs + msg)
else:
print("[X] " + "\t" * tabs + msg)
def dbg(msg, tabs=0):
print("[D] " + "\t" * tabs + msg)
def csv_to_vocab(filename, type, from_id):
id = from_id + 1
vocab = []
skip = 0
path = os.path.join(PATH_TO_VOCAB, filename)
dbg("Reading from {0} ({1})".format(filename, path), tabs=2)
with open(path, newline="") as csvfile:
reader = csv.reader(csvfile, delimiter=",", quotechar="\"")
for raw in reader:
skip += 1
# Skip the header lines
# if (skip < num_lines_to_skip + 1):
if (skip < 4):
continue
# The nouns are special
row = preprocess_row(raw) if type == TYPE_NOUNS else raw
grundform = row[0]
hint = ""
mnemonic = ""
latin = {
"grundform": grundform
}
# The parsing depends on the type of word we're dealing with
bedeutungen = []
if (type == TYPE_NOUNS):
# Nomen
genitiv = row[1]
genus = genus_to_datatype(row[2])
bedeutungen = [row[3]]
if (row[4] != ""):
bedeutungen.append(row[4])
if (row[5] != ""):
bedeutungen.append(row[5])
latin["genitiv"] = genitiv
latin["genus"] = genus
elif (type == TYPE_VERBS):
# Verb
praesens = row[1]
perfekt = row[2]
bedeutungen = [row[3]]
if (row[4] != ""):
bedeutungen.append(row[4])
if (row[5] != ""):
bedeutungen.append(row[5])
latin["praesens"] = praesens
latin["perfekt"] = perfekt
latin["ppp"] = ""
elif (type == TYPE_ADJECTIVES):
# Adjektiv
endung_f = row[1]
endung_n = row[2]
bedeutungen = [row[3]]
if (row[4] != ""):
bedeutungen.append(row[4])
if (row[5] != ""):
bedeutungen.append(row[5])
latin["nominativ_a"] = endung_f
latin["nominativ_b"] = endung_n
# TODO: Hints and mnemonics
vocab.append({
"id": id,
"german": bedeutungen,
"hint": hint,
"mnemonic": mnemonic,
"type": type,
"latin": latin
})
id += 1
return vocab, id
log("Lateinicus CSV to Vocabulary DB Model")
if (len(sys.argv) < 3):
log("Not enough arguments!", err=True)
log("Usage: csv_vocab_to_mongo.py <URI> <Database>", err=True)
sys.exit(1)
log("Generating vocabulary")
id = 0
vocab = []
# Nouns
log("Nouns...", tabs=1)
nouns, last_id = csv_to_vocab("Nomen.csv", TYPE_NOUNS, 0)
vocab += nouns
id = last_id
log("Verbs...", tabs=1)
verbs, last_id = csv_to_vocab("Verben.csv", TYPE_VERBS, last_id)
vocab += verbs
id = last_id
log("Adjectives...", tabs=1)
adj, last_id = csv_to_vocab("Adjektive.csv", TYPE_ADJECTIVES, last_id)
vocab += adj
id = last_id
sys.exit(1)
# Connect to the database
log("Inserting vocabulary into database")
log("Connecting...", tabs=1)
client = pymongo.MongoClient(sys.argv[1])
log("Getting DB...", tabs=1)
db = client[sys.argv[2]]
log("Inserting...", tabs=1)
res = db["vocabulary"].insert_many(vocab)
if (len(res.inserted_ids) != len(vocab)):
log("Not enough elements were added to the database", err=True, tabs=1)
else:
log("Success", tabs=1)

79
scripts/package-lock.json generated Normal file
View File

@ -0,0 +1,79 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"bson": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.0.tgz",
"integrity": "sha512-9Aeai9TacfNtWXOYarkFJRW2CWo+dRon+fuLZYJmvLV3+MiUp0bEI6IAZfXEIg7/Pl/7IWlLaDnhzTsD81etQA=="
},
"memory-pager": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.1.0.tgz",
"integrity": "sha512-Mf9OHV/Y7h6YWDxTzX/b4ZZ4oh9NSXblQL8dtPCOomOtZciEHxePR78+uHFLLlsk01A6jVHhHsQZZ/WcIPpnzg==",
"optional": true
},
"mongodb": {
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.1.6.tgz",
"integrity": "sha512-E5QJuXQoMlT7KyCYqNNMfAkhfQD79AT4F8Xd+6x37OX+8BL17GyXyWvfm6wuyx4wnzCCPoCSLeMeUN2S7dU9yw==",
"requires": {
"mongodb-core": "3.1.5",
"safe-buffer": "^5.1.2"
}
},
"mongodb-core": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.1.5.tgz",
"integrity": "sha512-emT/tM4ZBinqd6RZok+EzDdtN4LjYJIckv71qQVOEFmvXgT5cperZegVmTgox/1cx4XQu6LJ5ZuIwipP/eKdQg==",
"requires": {
"bson": "^1.1.0",
"require_optional": "^1.0.1",
"safe-buffer": "^5.1.2",
"saslprep": "^1.0.0"
}
},
"require_optional": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
"requires": {
"resolve-from": "^2.0.0",
"semver": "^5.1.0"
}
},
"resolve-from": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
"integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"saslprep": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.2.tgz",
"integrity": "sha512-4cDsYuAjXssUSjxHKRe4DTZC0agDwsCqcMqtJAQPzC74nJ7LfAJflAtC1Zed5hMzEQKj82d3tuzqdGNRsLJ4Gw==",
"optional": true,
"requires": {
"sparse-bitfield": "^3.0.3"
}
},
"semver": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
"integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw=="
},
"sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
"optional": true,
"requires": {
"memory-pager": "^1.0.2"
}
}
}
}