ajout de la section nim-lib

This commit is contained in:
bruno 2022-11-10 15:54:58 -05:00
parent e0d656f349
commit 9c0d9e8833
9 changed files with 6 additions and 869 deletions

View File

@ -1,132 +0,0 @@
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-08-09
#
# __ DESCRIPTIONS __
# database_utils : procedure related to database
#
# Inspiration of : https://ttj.dk/blog/2019/01/20/setup-a-website-with-nim
# Copyright 2019 - Thomas T. Jarløv
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
import os
import logging
import parsecfg
import db_sqlite
import ../code/password_utils
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : Generate Database
# --==--==--==--==--==--==--==--==--==--==-- #
proc generateDB*() =
echo "Generating database"
# Load the connection details
let
dict = loadConfig("config/config.cfg")
db_user = dict.getSectionValue("Database", "user")
db_pass = dict.getSectionValue("Database", "pass")
db_name = dict.getSectionValue("Database", "name")
db_host = dict.getSectionValue("Database", "host")
db_folder = dict.getSectionValue("Database", "folder")
dbexists = if fileExists(db_host): true else: false
if dbexists:
echo " - Database already exists. Inserting tables if they do not exist."
# Creating database folder if it doesn't exist
discard existsOrCreateDir(db_folder)
# Open DB
echo " - Opening database"
var db = open(connection = db_host, user = db_user, password = db_pass,
database = db_name)
# Person table contains information about the
# registrered users
if not db.tryExec(sql("""
create table if not exists person(
id integer primary key,
name varchar(60) not null,
password varchar(300) not null,
email varchar(254) not null,
creation timestamp not null default (STRFTIME('%s', 'now')),
modified timestamp not null default (STRFTIME('%s', 'now')),
salt varbin(128) not null,
status varchar(30) not null,
timezone VARCHAR(100),
secretUrl VARCHAR(250),
lastOnline timestamp not null default (STRFTIME('%s', 'now'))
);""")):
echo " - Database: person table already exists"
# Session table contains information about the users
# cookie ID, IP and last visit
if not db.tryExec(sql("""
create table if not exists session(
id integer primary key,
ip inet not null,
key varchar(300) not null,
userid integer not null,
lastModified timestamp not null default (STRFTIME('%s', 'now')),
foreign key (userid) references person(id)
);""")):
echo " - Database: session table already exists"
# Sesion table contains information about the search
#
if not db.tryExec(sql("""
create table if not exists search(
id integer primary key,
search_title varchar(300) not null,
query varchar(300) not null,
search_type varchar(100) not null,
creation timestamp not null default (STRFTIME('%s', 'now')),
lastModified timestamp not null default (STRFTIME('%s', 'now')),
foreign key (userid) references person(id)
);""")):
echo " - Database: search table already exists"
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : Create Administrator User
# --==--==--==--==--==--==--==--==--==--==-- #
proc createAdminUser*(db: DbConn, args: seq[string]) =
## Create new admin user
var iName = ""
var iEmail = ""
var iPwd = ""
# Loop through all the arguments and get the args
# containing the user information
for arg in args:
if arg.substr(0, 1) == "u:":
iName = arg.substr(2, arg.len())
elif arg.substr(0, 1) == "p:":
iPwd = arg.substr(2, arg.len())
elif arg.substr(0, 1) == "e:":
iEmail = arg.substr(2, arg.len())
# If the name, password or emails does not exists
# return error
if iName == "" or iPwd == "" or iEmail == "":
error("Missing either name, password or email to create the Admin user.")
# Generate the password using a salt and hashing.
# Read more about hashing and salting here:
# - https://crackstation.net/hashing-security.htm
# - https://en.wikipedia.org/wiki/Salt_(cryptography)
let salt = makeSalt()
let password = makePassword(iPwd, salt)
# Insert user into database
if insertID(db, sql"INSERT INTO person (name, email, password, salt, status) VALUES (?, ?, ?, ?, ?)",
$iName, $iEmail, password, salt, "Admin") > 0:
echo "Admin user added"
else:
error("Something went wrong")
info("Admin added.")

View File

@ -1,24 +0,0 @@
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-08-09
#
# __ DESCRIPTIONS __
# joplin_json_utils : Types and procedure related to json request
#
# [TODO] joplin_json_utils : need to create many procedures
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Data structure for TAGS
# --==--==--==--==--==--==--==--==--==--==-- #
type Tag = object
id : string
parent_id : string
title: string
type Tags = object
items: seq[Tag]
has_more: string

View File

@ -1,516 +0,0 @@
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-08-09
#
# __ DESCRIPTIONS __
# joplin_utils : procedure related joplin application
#
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
import os
import net
import times
import osproc
import jester
import std/json
import httpcore
import strutils
import strformat
import std/options
import std/httpclient
import std/asyncdispatch
import utils # Joplin utils procedures and types
# from os import sleep
from posix import read, write, fdatasync, close
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Setup joplin_ping data
# --==--==--==--==--==--==--==--==--==--==-- #
type
joplin_ping* = object
ping_result*: seq[string]
ping_status*: bool
req*: Request
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Setup joplin_tags data
# --==--==--==--==--==--==--==--==--==--==-- #
type
joplin_tags* = object
id*, parent_id*, title*: seq[string]
created_time*, updated_time*, user_created_time*, user_updated_time*,
is_shared*: seq[int]
req*: Request
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Setup joplin_notebooks data
# --==--==--==--==--==--==--==--==--==--==-- #
type
joplin_notebooks* = object
id*, parent_id*, title*, share_id*, icon*: seq[string]
created_time*, updated_time*, user_created_time*, user_updated_time*,
is_shared*: seq[int]
req*: Request
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Setup joplin_notes data
# --==--==--==--==--==--==--==--==--==--==-- #
type
joplin_notes* = object
id*, parent_id*, title*, body*, author*, source_url*, source*,
source_application*, application_data*, share_id*,
conflict_original_id*, body_html*, base_url*: seq[string]
updated_time*, is_conflict*, is_todo*, todo_due*,
todo_completed*, user_created_time*, user_updated_time*,
markup_language*, is_shared*: seq[int]
latitude*, longitude*, altitude*, order*: seq[float]
created_time*: seq[string]
req*: Request
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Setup joplin_note data
# --==--==--==--==--==--==--==--==--==--==-- #
type
joplin_note* = object
id*, parent_id*, title*, body*, author*, source_url*, source*,
source_application*, application_data*, conflict_original_id*,
master_key_id*, share_id*, encryption_cipher_text * : string
created_time*, updated_time*, user_created_time*, user_updated_time*,
is_conflict*, is_todo*, todo_due*, todo_completed*, markup_language*,
is_shared*, encryption_applied*: int
latitude*, longitude*, altitude*, order*: float
req*: Request
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Setup process data structure
# --==--==--==--==--==--==--==--==--==--==-- #
type
program* = object
pid*: int
stdout*: string
stderr*: string
# --==--==--==--==--==--==--==--==--==--==-- #
# DURATION : duration variables
# --==--==--==--==--==--==--==--==--==--==-- #
let
resetDuration = initDuration(seconds = 2)
deciSecondDuration* = initDuration(milliseconds = 100)
qtrsecondDuration* = initDuration(milliseconds = 250)
# --==--==--==--==--==--==--==--==--==--==-- #
# VAR : connexion http variables
# --==--==--==--==--==--==--==--==--==--==-- #
var
client = newHttpClient()
lastConnection = getTime().utc
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : reset HTTP client
# --==--==--==--==--==--==--==--==--==--==-- #
proc resetHttpClient() =
if (getTime().utc - lastConnection) > resetDuration:
# Probably a new timeout. We have not yet experienced a long outage.
# We may however be entering an extended outage.
# Creating the new clients seems to use up lots of CPU.
# I want to do that as little as possible.
try:
client.close()
except:
echo("Attempted to close clients. Probably do not exist.")
echo("Current exception: ", getCurrentExceptionMsg())
client = newHttpClient(timeout = 500)
# --==--==--==--==--==--==--==--==--==--==--==--==--==-==--==--==- #
# PROC : use the joplin API ping to validate service availibility
# --==--==--==--==--==--==--==--==--==--==--==--==--==-==--==--==- #
proc ping_joplin*(token: string): Future[joplin_ping] {.async.} =
var j_p: joplin_ping
var client = newAsyncHttpClient()
var url: string
j_p.ping_status = false
try:
url = fmt"http://localhost:41184/ping?token={token}"
var json = await client.getContent(url)
j_p.ping_result.add(json)
echo j_p.ping_result[0]
if j_p.ping_result[0] == "JoplinClipperServer":
j_p.ping_status = true
except TimeoutError, IOError, OSError:
# I naively think I would see this thrown or the plain except below.
# But I almost never see an Error raised.
echo("Current Exception: ", getCurrentException().name)
echo("Current Exception Msg: ", getCurrentExceptionMsg())
echo("Sleeping for 1 seconds at: ", getTime().utc)
sleep(500)
resetHttpClient()
j_p.ping_status = false
except:
echo("Current Exception: ", getCurrentException().name)
echo("Current Exception Msg: ", getCurrentExceptionMsg())
echo("Sleeping for 1 seconds at: ", getTime().utc)
j_p.ping_status = false
return j_p
# parse jason
#let joplin_notes_Json = parseJson(json)
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : get all joplin NOTEBOOKS
# --==--==--==--==--==--==--==--==--==--==-- #
proc get_joplin_notebooks*(token: string): Future[joplin_notebooks] {.async.} =
# Variables
var j_nb: joplin_notebooks
var has_more: bool = true
var page: int = 1
var url: string
var client = newAsyncHttpClient()
var pingCheck: joplin_ping
pingCheck = waitFor ping_joplin(token)
# check the joplin status befor query
if pingCheck.ping_status:
# make sure to check all pages
while has_more == true:
# request joplin API for notebooks
url = fmt"http://localhost:41184/folders?page={page}&token={token}"
echo("URL notebooks : ", url)
var json = await client.getContent(url)
# parse jason
let joplin_notebooks_Json = parseJson(json)
# valider qu'il n'y a plus de page
if not joplin_notebooks_Json["has_more"].getBool:
has_more = false
# store json info into an object
var count: int = 1
for nb in joplin_notebooks_Json["items"]:
j_nb.id.add(nb["id"].getstr)
j_nb.parent_id.add(nb["parent_id"].getstr)
j_nb.title.add(nb["title"].getstr)
count += 1
# aller à la page suivante
page += 1
return j_nb
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : get all joplin NOTES
# --==--==--==--==--==--==--==--==--==--==-- #
proc get_joplin_notes*(token: string): Future[joplin_notes] {.async.} =
# Variables
var j_notes: joplin_notes
var has_more: bool = true
var page: int = 1
var url: string
var client = newAsyncHttpClient()
var pingCheck: joplin_ping
pingCheck = waitFor ping_joplin(token)
# check the joplin status befor query
if pingCheck.ping_status:
# make sure to check all pages
while has_more == true:
# request joplin API for Notes
url = fmt"http://localhost:41184/notes?page={page}&fields=id,parent_id,title,created_time,updated_time&token={token}"
echo("URL notes : ", url)
var json = await client.getContent(url)
# parse jason
let joplin_notes_Json = parseJson(json)
# valider qu'il n'y a plus de page
if not joplin_notes_Json["has_more"].getBool:
has_more = false
#echo joplin_notes_Json
# store json info into an object
var count: int = 1
var epochTime: int
var humanTime: Time
for nb in joplin_notes_Json["items"]:
j_notes.id.add(nb["id"].getstr)
j_notes.parent_id.add(nb["parent_id"].getstr)
j_notes.title.add(nb["title"].getstr)
#epochTime = nb["created_time"].getInt
#humanTime = fromUnix(convert(Milliseconds, Seconds, epochTime))
j_notes.created_time.add(convertEpochToHumanTime(nb[
"created_time"].getInt))
count += 1
# aller à la page suivante
page += 1
return j_notes
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : get joplin NOTE
# --==--==--==--==--==--==--==--==--==--==-- #
proc get_joplin_note*(token: string, noteid: string): Future[
joplin_note] {.async.} =
# Variables
var j_note: joplin_note
var has_more: bool = true
var page: int = 1
var url: string
var client = newAsyncHttpClient()
# Check joplin connection availibility
var pingCheck: joplin_ping
pingCheck = waitFor ping_joplin(token)
# Query for a selected note
url = fmt"http://localhost:41184/notes/{noteid}?fields=id,parent_id,title,body,created_time,updated_time,is_conflict,latitude,longitude,altitude,author,source_url,is_todo,todo_due,todo_completed,source,source_application,application_data,order,user_created_time,user_updated_time,encryption_cipher_text,encryption_applied,markup_language,is_shared,share_id,conflict_original_id,master_key_id&token={token}"
echo("URL notes : ", url)
var jsonNote = await client.getContent(url)
# parse jason
let joplin_note_Json = parseJson(jsonNote)
# get all informations for a selected note
j_note.id = joplin_note_Json["id"].getstr
j_note.parent_id = joplin_note_Json["parent_id"].getstr
j_note.title = joplin_note_Json["title"].getstr
j_note.body = joplin_note_Json["body"].getstr
j_note.author = joplin_note_Json["author"].getstr
j_note.source_url = joplin_note_Json["source_url"].getstr
j_note.source = joplin_note_Json["source"].getstr
j_note.source_application = joplin_note_Json["source_application"].getstr
j_note.application_data = joplin_note_Json["application_data"].getstr
j_note.share_id = joplin_note_Json["share_id"].getstr
j_note.conflict_original_id = joplin_note_Json["conflict_original_id"].getstr
j_note.created_time = joplin_note_Json["created_time"].getInt
j_note.updated_time = joplin_note_Json["updated_time"].getInt
j_note.is_conflict = joplin_note_Json["is_conflict"].getInt
j_note.latitude = joplin_note_Json["latitude"].getFloat
j_note.longitude = joplin_note_Json["longitude"].getFloat
j_note.altitude = joplin_note_Json["altitude"].getFloat
j_note.is_todo = joplin_note_Json["is_todo"].getInt
j_note.todo_due = joplin_note_Json["todo_due"].getInt
j_note.todo_completed = joplin_note_Json["todo_completed"].getInt
j_note.order = joplin_note_Json["order"].getFloat
j_note.user_created_time = joplin_note_Json["user_created_time"].getInt
j_note.user_updated_time = joplin_note_Json["user_updated_time"].getInt
j_note.encryption_cipher_text = joplin_note_Json[
"encryption_cipher_text"].getstr
j_note.encryption_applied = joplin_note_Json["encryption_applied"].getInt
j_note.markup_language = joplin_note_Json["markup_language"].getInt
j_note.is_shared = joplin_note_Json["is_shared"].getInt
j_note.master_key_id = joplin_note_Json["master_key_id"].getstr
echo j_note
return j_note
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : get all joplin TAGS
# --==--==--==--==--==--==--==--==--==--==-- #
proc get_joplin_tags*(token: string): Future[joplin_tags] {.async.} =
# Variables
var j_tags: joplin_tags
var has_more: bool = true
var page: int = 1
var url: string
var client = newAsyncHttpClient()
var pingCheck: joplin_ping
pingCheck = waitFor ping_joplin(token)
# check the joplin status befor query
if pingCheck.ping_status:
# make sure to check all pages
while has_more == true:
# request joplin API for notebooks
url = fmt"http://localhost:41184/tags?page={page}&token={token}"
echo("URL tags : ", url)
var json = await client.getContent(url)
# parse jason
let joplin_tags_Json = parseJson(json)
# valider qu'il n'y a plus de page
if not joplin_tags_Json["has_more"].getBool:
has_more = false
# store json info into an object
var count: int = 1
for nb in joplin_tags_Json["items"]:
j_tags.id.add(nb["id"].getstr)
j_tags.parent_id.add(nb["parent_id"].getstr)
j_tags.title.add(nb["title"].getstr)
count += 1
# aller à la page suivante
page += 1
return j_tags
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : get the token from Joplin Terminal
# --==--==--==--==--==--==--==--==--==--==-- #
proc get_joplin_cli_token*(): string =
var flagName: string = ""
var flagValue: string = ""
var result = execCmdEx("joplin config api.token")
if result.exitCode == 0:
let param1 = result.output
let flagSplit = param1.split(" = ")
flagName = flagSplit[0]
flagValue = flagSplit[1]
return flagValue
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : launch any program and get PID
# --==--==--==--==--==--==--==--==--==--==-- #
proc launchProgram(app: string = "", workingPath: string = "", arguments: array[
2, string]): int {.thread.} =
var p = startProcess(joinPath(workingPath, app), workingPath, arguments)
let pid = p.processID()
var outhdl = outputHandle(p)
var inputhdl = inputHandle(p)
var errhdl = errorHandle(p)
return pid
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : Start joplin cli
# --==--==--==--==--==--==--==--==--==--==-- #
proc joplin_cli_start*(): int {.thread.} =
let joplinProcessId = launchProgram("joplin", "/usr/bin/", ["server", "start"])
return joplinProcessId
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : stop Joplin Terminal
# --==--==--==--==--==--==--==--==--==--==-- #
proc joplin_cli_stop*(): int {.thread.} =
let joplinProcessId = launchProgram("joplin", "/usr/bin/", ["server", "stop"])
return joplinProcessId
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : check Joplin Terminal staus
# --==--==--==--==--==--==--==--==--==--==-- #
proc joplin_cli_status*(): bool =
var rc = false
var result = execCmdEx("joplin server status")
if result.exitCode == 0:
if "Server is not running" in result.output:
echo "Joplin Terminal cli status is down : ", result.output
rc = false
else:
echo "Joplin Terminal cli status is up : ", result.output
rc = true
else:
echo "Error validate joplin terminal status : ", result.output
return rc
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : start or stop Joplin Terminal
# --==--==--==--==--==--==--==--==--==--==-- #
proc joplin_cli_start_stop*(): int =
var isStart: int = 0
var sleep_delay_frame: int = 50
var sleep_max: int = 5000
if joplin_cli_status() == false:
isStart = joplin_cli_start()
while joplin_cli_status() == false:
sleep(sleep_delay_frame)
echo "Joplin client Terminal started: ", isStart
else:
echo "Joplin client Terminal is alredy started !"
#if joplin_cli_status() == true:
isStart = joplin_cli_stop()
while joplin_cli_status() == true:
sleep(sleep_delay_frame)
echo "Joplin client Terminal stopped: ", isStart
return isStart
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC :
# --==--==--==--==--==--==--==--==--==--==-- #
# proc get_joplin_tags_json*(token:string): Future[] {.async.} =
# # url = fmt"http://localhost:41184/notes/{id}?fields=id,parent_id,title,body,created_time,updated_time,is_conflict,latitude,longitude,altitude,author,source_url,is_todo,todo_due,todo_completed,source,source_application,application_data,order,user_created_time,user_updated_time,encryption_cipher_text,encryption_applied,markup_language,is_shared,share_id,conflict_original_id,master_key_id&token={token}"
# # url = fmt"http://localhost:41184/tags/{id}?fields=id,parent_id,title,created_time,updated_time,user_created_time,user_updated_time,is_shared&token={token}"
# # http://localhost:41184/tags?token=e5f6644fbf6a97ddc55648dae72b11caecda6c6642d8ce0d3b20129b89b196385737eb908923542c3343649ebbf865b55bda031ab4c3a16edc7723ef2ad77d8f
# # Variables
# var j_tags: joplin_tags
# var has_more: bool = true
# var page: int = 1
# var url: string
# var client = newAsyncHttpClient()
# var pingCheck: joplin_ping
# pingCheck = waitFor ping_joplin(token)
# # check the joplin status befor query
# if pingCheck.ping_status:
# # make sure to check all pages
# while has_more == true:
# # request joplin API for notebooks
# url = fmt"http://localhost:41184/tags?page={page}&token={token}"
# echo("URL tags : ", url)
# var json = await client.getContent(url)
# # parse jason
# let joplin_tags_Json = parseJson(json)
# # valider qu'il n'y a plus de page
# if not joplin_tags_Json["has_more"].getBool:
# has_more = false
# # store json info into an object
# var count: int = 1
# for nb in joplin_tags_Json["items"]:
# echo nb["id"].getstr
# echo nb["parent_id"].getstr
# echo nb["title"].getstr
# count += 1
# # aller à la page suivante
# page += 1

View File

@ -1,56 +0,0 @@
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-08-09
#
# __ DESCRIPTIONS __
# password_utils : procedure related password
#
# Inspiration of : https://ttj.dk/blog/2019/01/20/setup-a-website-with-nim
# Copyright 2019 - Thomas T. Jarløv
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
import md5
import bcrypt
import random
randomize()
# --==--==--==--==--==--==--==--==--==--==-- #
# Let and VAR : for random
# --==--==--==--==--==--==--==--==--==--==-- #
var urandom: File
let useUrandom = urandom.open("/dev/urandom")
# --==--==--==--==--==--==--==--==--==--==--=--==--==--=--==--==--=--==--==-- #
# PROC : Make Salt
## : Generate random salt. Uses cryptographically secure /dev/urandom
## : on platforms where it is available, and Nim's random module in other cases.
# --==--==--==--==--==--==--==--==--==--==--=--==--==--=--==--==--=--==--==-- #
proc makeSalt*(): string =
result = ""
if useUrandom:
var randomBytes: array[0..127, char]
discard urandom.readBuffer(addr(randomBytes), 128)
for ch in randomBytes:
if ord(ch) in {32..126}:
result.add(ch)
else:
for i in 0..127:
result.add(chr(rand(94) + 32)) # Generate numbers from 32 to 94 + 32 = 126
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : Make session key
## Creates a random key to be used to authorize a session.
# --==--==--==--==--==--==--==--==--==--==-- #
proc makeSessionKey*(): string =
let random = makeSalt()
return bcrypt.hash(random, genSalt(8))
# --==--==--==--==--==--==--==--==--==--==-- #
# PROC : make password
## Creates an MD5 hash by combining password and salt
# --==--==--==--==--==--==--==--==--==--==-- #
proc makePassword*(password, salt: string, comparingTo = ""): string =
let bcryptSalt = if comparingTo != "": comparingTo else: genSalt(8)
result = hash(getMD5(salt & getMD5(password)), bcryptSalt)

View File

@ -1,22 +0,0 @@
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-10-25
#
# __ DESCRIPTIONS __
# utils : procedures generals utils
#
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
import std/times
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# PROC : Convert epoch millisecond time to human readable time
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
proc convertEpochToHumanTime*(epochTime: int): string =
var humanTime: Time
var dateTime: string
humanTime = fromUnix(convert(Milliseconds, Seconds, epochTime))
dateTime = format(humanTime, "yyyy-MM-dd' 'HH:mm")
# echo dateTime
return dateTime

View File

@ -1,113 +0,0 @@
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# Bruno Charest
# 2022-08-09
#
# __ DESCRIPTIONS __
# web_utils : procedure related web interface
#
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
import xlsx # read dashbord.xlsx
import jester
import joplin_utils
import strutils
import std/asyncdispatch
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Selected Option for master web page
# --==--==--==--==--==--==--==--==--==--==-- #
type
selectedOption* = enum
newNote = "New Note", search = "Search", shortcuts = "Shortcuts",
notes = "Notes", notebooks = "Notesbooks", tags = "Tags",
notes_selectednote = "Notes-SelectedNote", dashbord = "Dashboard"
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Dashbord information
# --==--==--==--==--==--==--==--==--==--==-- #
type DashbordData* = object
position*: seq[int]
ext_link*: seq[string]
int_link*: seq[string]
ip_link*: seq[string]
title*: seq[string]
description*: seq[string]
server*: seq[string]
ip*: seq[string]
port*: seq[int]
ssl*: seq[bool]
category*: seq[string]
icon*: seq[string]
open_method*: seq[string]
tag*: seq[seq[string]]
hotkey*: seq[string]
color*: seq[string]
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Data Informations for Left Colomn
# --==--==--==--==--==--==--==--==--==--==-- #
type ColomnLeftData* = ref object of RootObj
j_status*: bool
option*: selectedOption
j_notes*: joplin_notes
j_notes_nb*: int
j_notebooks*: joplin_notebooks
j_notebooks_nb*: int
j_tags*: joplin_tags
j_tags_nb*: int
dashbord*: DashbordData
req*: Request
# --==--==--==--==--==--==--==--==--==--==-- #
# TYPE : Data Informations for Right Colomn
# --==--==--==--==--==--==--==--==--==--==-- #
type ColomnRightData* = ref object of RootObj
j_status*: bool
option*: selectedOption
j_SelectedNote*: joplin_note
j_notebooksNote*: joplin_notebooks
j_tagsNote*: joplin_tags
req*: Request
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
# PROC : get data from dashbord file
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
proc getDashbordData*(): Future[DashbordData] {.async.} =
var ddata: DashbordData
var tagslist: seq[string]
let
data = parseExcel("data/dashbord.xlsx", header = true)
sheetName = "dashbord"
#echo data[sheetName]
let rows = data[sheetName].toSeq(true)
echo rows.len()
for i in 0..(rows.len()-1):
ddata.position.add(parseInt(rows[i][0]))
ddata.ext_link.add(rows[i][1])
ddata.int_link.add(rows[i][2])
ddata.ip_link.add(rows[i][3])
ddata.title.add(rows[i][4])
ddata.description.add(rows[i][5])
ddata.server.add(rows[i][6])
ddata.ip.add(rows[i][7])
ddata.port.add(parseInt(rows[i][8]))
if rows[i][9] == "OUI":
ddata.ssl.add(true)
else:
ddata.ssl.add(false)
ddata.category.add(rows[i][10])
ddata.icon.add(rows[i][11])
ddata.open_method.add(rows[i][12])
tagslist = rows[i][13].split(',')
ddata.tag.add(tagslist)
ddata.hotkey.add(rows[i][14])
ddata.color.add(rows[i][15])
echo ddata
return ddata

View File

@ -27,10 +27,10 @@ import parsecfg # Parse CFG (config) files
import std/json # json manipulation
import db_sqlite # SQLite
import code/database_utils # Utils used in the database
import code/password_utils # Our file with password utils
import code/joplin_utils # Joplin utils procedures and types
import code/web_utils # Web utils procedures and types
import nim-lib/outils/db/database_utils # Utils used in the database
import nim-lib/outils/commun/password_utils # Our file with password utils
import nim-lib/outils/communication/joplin/joplin_utils # Joplin utils procedures and types
import nim-lib/outils/web/web_utils # Web utils procedures and types
# --==--==--==--==--==--==--==--==--==--==-- #
# First we'll load config files

@ -1 +1 @@
Subproject commit 6ad56e141aa49e01fffc49236dc93868c6c770a9
Subproject commit 88f05c55299a451e673c2fb277ce71f677054b47

View File

@ -1,5 +1,5 @@
import templates
import ../code/web_utils
import ../nim-lib/outils/web/web_utils
# --==--==--==--==--==--==--==--==--==--==-- #
# SVG : HTML title H2