ajout de la section nim-lib
This commit is contained in:
		
							parent
							
								
									e0d656f349
								
							
						
					
					
						commit
						9c0d9e8833
					
				@ -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.")
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
							
								
								
									
										8
									
								
								main.nim
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								main.nim
									
									
									
									
									
								
							@ -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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								nim-lib
									
									
									
									
									
								
							
							
								
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								nim-lib
									
									
									
									
									
								
							@ -1 +1 @@
 | 
			
		||||
Subproject commit 6ad56e141aa49e01fffc49236dc93868c6c770a9
 | 
			
		||||
Subproject commit 88f05c55299a451e673c2fb277ce71f677054b47
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import templates
 | 
			
		||||
import ../code/web_utils
 | 
			
		||||
import ../nim-lib/outils/web/web_utils
 | 
			
		||||
 | 
			
		||||
# --==--==--==--==--==--==--==--==--==--==-- #
 | 
			
		||||
# SVG : HTML title H2
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user