Starting new code pre v2
This commit is contained in:
parent
75b42a68d4
commit
6a17add248
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,13 +1,13 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
Tyto - Littérateur
|
Tyto - Littérateur
|
||||||
- Repository: https://git.a-lec.org/echolib/tyto-litterateur
|
- Repository:
|
||||||
- Issues: https://git.a-lec.org/echolib/tyto-litterateur/-/issues
|
- Issues:
|
||||||
- Changelog: https://git.a-lec.org/echolib/tyto-litterateur/-/blob/master/CHANGELOG.md
|
- Changelog:
|
||||||
- License: https://git.a-lec.org/echolib/tyto-litterateur/-/blob/master/LICENSE
|
- License:
|
||||||
- Documentation: https://tyto.echolib.re
|
- Documentation:
|
||||||
|
|
||||||
## [0.10.6]
|
## [1.9.0]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
57
README.md
57
README.md
|
@ -1,53 +1,14 @@
|
||||||
# Tyto
|
# Very early IN dev code
|
||||||
- FR. Pour obtenir de l'aide, taper juste la commande tyto
|
This program can ve tested but not at all usable. Lots of work to do...
|
||||||
- EN. To get help, just type tyto.
|
|
||||||
- - Doc is only in french yet, but Tyto is translated, also for your websites
|
|
||||||
|
|
||||||
## Répertoire de code du projet Tyto
|
# Commands
|
||||||
https://git.a-lec.org/echolib/tyto-litterateur
|
|
||||||
|
|
||||||
## Documentation officielle
|
|
||||||
https://tyto.echolib.re (en cours de construction)
|
|
||||||
|
|
||||||
## Créer un domaine
|
|
||||||
````
|
|
||||||
mkdir -p MONDOMAIN
|
|
||||||
cd MONDOMAIN
|
|
||||||
tyto new domain URL
|
|
||||||
````
|
|
||||||
|
|
||||||
# Créer un article
|
|
||||||
https://tyto.echolib.re/%C3%A9crire/
|
|
||||||
```
|
```
|
||||||
cd articles/
|
# Get commands list help
|
||||||
tyto new index
|
tyto
|
||||||
tyto edit index.tyto
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Vérifier, prévisualiser un article
|
# Working on
|
||||||
```
|
- Managing domain(s)
|
||||||
tyto check index.tyto
|
- - needs more checks to be validated
|
||||||
tyto wip index.tyto
|
- english logs translation file (French only, for now)
|
||||||
```
|
|
||||||
|
|
||||||
# Les modules
|
|
||||||
https://tyto.echolib.re/usages/modules.html
|
|
||||||
|
|
||||||
La barre latérale, le menu, le pied de page et les balises génériques metas
|
|
||||||
ne seront pas visible localement sans serveur nginx.
|
|
||||||
|
|
||||||
Utiliser l'option --static avec la commande wip pour les voir. Attention,
|
|
||||||
utiliser la commande publish après avoir utilisé l'option --static sur wip
|
|
||||||
mettra en ligne la version statique de la page. Il faut donc avant la
|
|
||||||
commande publish, recommencer la commande wip sur un article sans l'option
|
|
||||||
--static pour utiliser l'include de nginx (comportement par défaut)
|
|
||||||
|
|
||||||
|
|
||||||
# Publier !
|
|
||||||
```
|
|
||||||
# La première fois, ou après mise à jour des modules ou des fichiers (logo, css...)
|
|
||||||
tyto publish template
|
|
||||||
|
|
||||||
# Mettre dans le dossier "www" officiel
|
|
||||||
tyto publish index.tyto
|
|
||||||
```
|
|
||||||
|
|
102
src/usr/bin/tyto
102
src/usr/bin/tyto
|
@ -1,93 +1,59 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Version: 1.0.0
|
# Version: 1.9.0
|
||||||
# Tyto - Littérateur
|
# Tyto - Littérateur
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License
|
# it under the terms of the GNU General Public License as published by
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# License, or of the License, or (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU Affero General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# XMPP: echolib (im@echolib.re)
|
# XMPP: echolib (im@echolib.re)
|
||||||
#
|
#
|
||||||
# Description: Main binary to execute
|
# Description: Main binary to execute.
|
||||||
|
# Import modules and start checking/using arguments
|
||||||
# File: /usr/bin/tyto
|
# File: /usr/bin/tyto
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
#-------------------------
|
#-------------------------
|
||||||
# Funny Stats Project
|
# Funny Stats Project
|
||||||
#-------------------------
|
#-------------------------
|
||||||
# Project files : 20
|
# Project files :
|
||||||
# Project lines : 7508
|
# Project lines :
|
||||||
# Project comments : 1153
|
# Project comments :
|
||||||
# Project functions: 109
|
# Project functions:
|
||||||
# Project program : 5652
|
# Project program :
|
||||||
#
|
#
|
||||||
# file lines : 93
|
# file lines :
|
||||||
# file comments : 33
|
# file comments :
|
||||||
# file functions: 0
|
# file functions:
|
||||||
# file program : 47
|
# file program :
|
||||||
#--------------------------
|
#--------------------------
|
||||||
|
|
||||||
|
#======#
|
||||||
|
# MAIN #
|
||||||
|
#======#=======================================================================
|
||||||
import sys
|
import sys
|
||||||
sys.path.insert(0, '/var/lib/tyto/program')
|
|
||||||
|
|
||||||
#====================#
|
|
||||||
# MAIN #
|
|
||||||
# Treat Arguments #
|
|
||||||
#--------------------#
|
|
||||||
import logs
|
|
||||||
|
|
||||||
if not __name__ == "__main__":
|
if not __name__ == "__main__":
|
||||||
logs.out("14", '', True)
|
print("! Error: '%s' not '%s'"%(__name__, "__main__"))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# Check arguments
|
# Set librairies to import app files
|
||||||
|
libs = "/var/lib/tyto/program"
|
||||||
|
trfs = "/var/lib/tyto/translations"
|
||||||
|
sys.path.insert(0, libs)
|
||||||
|
sys.path.insert(0, trfs)
|
||||||
|
|
||||||
|
# Manage arguments from command line, start process
|
||||||
import args
|
import args
|
||||||
action = args.set_action()
|
args.start_process()
|
||||||
target = args.set_target()
|
|
||||||
|
|
||||||
# Check domain
|
|
||||||
import dom, status
|
|
||||||
status.domain()
|
|
||||||
|
|
||||||
|
|
||||||
# Command start argument
|
|
||||||
import check, form, html, new, publish, show, wip, infos, creators
|
|
||||||
actions = {
|
|
||||||
"check" : check.manage,
|
|
||||||
"help" : infos.tyto,
|
|
||||||
"edit" : show.manage,
|
|
||||||
"edit-about" : show.manage,
|
|
||||||
"edit-db" : show.manage,
|
|
||||||
"edit-wip" : show.manage,
|
|
||||||
"edit-www" : show.manage,
|
|
||||||
"force-wip" : wip.manage,
|
|
||||||
"new" : new.manage,
|
|
||||||
"publish" : publish.manage,
|
|
||||||
"preview" : show.manage,
|
|
||||||
"quick-pub" : publish.manage,
|
|
||||||
"show" : show.manage,
|
|
||||||
"show-about" : show.manage,
|
|
||||||
"show-db" : show.manage,
|
|
||||||
"show-wip" : show.manage,
|
|
||||||
"show-www" : show.manage,
|
|
||||||
"status" : status.check,
|
|
||||||
"wip" : wip.manage,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Start action
|
|
||||||
# Argument's Check done in args.py
|
|
||||||
#---------------------------------
|
|
||||||
actions[action](target)
|
|
||||||
|
|
||||||
|
|
|
@ -1,311 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Tyto - Littérateur
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License
|
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# XMPP: echolib (im@echolib.re)
|
|
||||||
#
|
|
||||||
# Description: Autocompletion commands
|
|
||||||
# File: /usr/share/bash-completion/completions/tyto
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#-------------------------
|
|
||||||
# Funny Stats Project
|
|
||||||
#-------------------------
|
|
||||||
# file lines : 311
|
|
||||||
# file comments : 45
|
|
||||||
# file functions: 0
|
|
||||||
# file program : 234
|
|
||||||
#--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
#=================#
|
|
||||||
# Actions section #
|
|
||||||
#=================#============================================================
|
|
||||||
|
|
||||||
# Actions: argument 1 #
|
|
||||||
#---------------------#
|
|
||||||
_tyto_actions() {
|
|
||||||
cat <<EOL
|
|
||||||
check
|
|
||||||
domains
|
|
||||||
edit
|
|
||||||
edit-about
|
|
||||||
edit-db
|
|
||||||
edit-wip
|
|
||||||
edit-www
|
|
||||||
force-wip
|
|
||||||
help
|
|
||||||
new
|
|
||||||
show
|
|
||||||
show-about
|
|
||||||
show-db
|
|
||||||
show-wip
|
|
||||||
show-www
|
|
||||||
preview
|
|
||||||
publish
|
|
||||||
quick-pub
|
|
||||||
status
|
|
||||||
version
|
|
||||||
wip
|
|
||||||
EOL
|
|
||||||
}
|
|
||||||
|
|
||||||
_tyto_actions_only() {
|
|
||||||
grep -F -q -x "$1" <<EOL
|
|
||||||
domains
|
|
||||||
help
|
|
||||||
version
|
|
||||||
EOL
|
|
||||||
}
|
|
||||||
|
|
||||||
# Actions for articles and modules
|
|
||||||
#--------------------------------
|
|
||||||
_tyto_actions_wp() {
|
|
||||||
grep -F -q -x "$1" <<EOL
|
|
||||||
publish
|
|
||||||
wip
|
|
||||||
EOL
|
|
||||||
}
|
|
||||||
|
|
||||||
# Actions for edit
|
|
||||||
#-----------------
|
|
||||||
_tyto_actions_edits() {
|
|
||||||
grep -F -q -x "$1" <<EOL
|
|
||||||
edit
|
|
||||||
edit-about
|
|
||||||
edit-db
|
|
||||||
edit-wip
|
|
||||||
edit-www
|
|
||||||
EOL
|
|
||||||
}
|
|
||||||
|
|
||||||
# Actions for show
|
|
||||||
#-----------------
|
|
||||||
_tyto_actions_shows() {
|
|
||||||
grep -F -q -x "$1" <<EOL
|
|
||||||
show
|
|
||||||
show-about
|
|
||||||
show-db
|
|
||||||
show-wip
|
|
||||||
show-www
|
|
||||||
EOL
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#=================#
|
|
||||||
# Targets section #
|
|
||||||
#=================#============================================================
|
|
||||||
|
|
||||||
# Targets for articles and modules
|
|
||||||
#--------------------------------
|
|
||||||
_tyto_targets_wp() {
|
|
||||||
cat <<EOL
|
|
||||||
added
|
|
||||||
again
|
|
||||||
footer
|
|
||||||
metas
|
|
||||||
navbar
|
|
||||||
sidebar
|
|
||||||
stats
|
|
||||||
template
|
|
||||||
updated
|
|
||||||
EOL
|
|
||||||
|
|
||||||
find . -type f -name "*.tyto" -printf '%P\n' 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
# Targets with quick-pub
|
|
||||||
#-----------------------
|
|
||||||
_tyto_targets_qp() {
|
|
||||||
find . -type f -name "*.tyto" -printf '%P\n' 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Targets with edit
|
|
||||||
#------------------
|
|
||||||
_tyto_targets_edits() {
|
|
||||||
cat <<EOL
|
|
||||||
domain
|
|
||||||
footer
|
|
||||||
metas
|
|
||||||
navbar
|
|
||||||
sidebar
|
|
||||||
EOL
|
|
||||||
|
|
||||||
find . -type f -name "*.tyto" -printf '%P\n' 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
# Targets with edit
|
|
||||||
#------------------
|
|
||||||
_tyto_targets_shows() {
|
|
||||||
cat <<EOL
|
|
||||||
domain
|
|
||||||
footer
|
|
||||||
metas
|
|
||||||
navbar
|
|
||||||
sidebar
|
|
||||||
stats
|
|
||||||
EOL
|
|
||||||
|
|
||||||
find . -type f -name "*.tyto" -printf '%P\n' 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
# Targets: argument 2 (all + .tyto files)
|
|
||||||
#----------------------------------------
|
|
||||||
_tyto_targets() {
|
|
||||||
cat <<EOL
|
|
||||||
added
|
|
||||||
again
|
|
||||||
domain
|
|
||||||
footer
|
|
||||||
metas
|
|
||||||
navbar
|
|
||||||
sidebar
|
|
||||||
stats
|
|
||||||
template
|
|
||||||
updated
|
|
||||||
EOL
|
|
||||||
|
|
||||||
find . -type f -name "*.tyto" -printf '%P\n' 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
# Targets: only with action "new"
|
|
||||||
#--------------------------------
|
|
||||||
_tyto_targets_new() {
|
|
||||||
cat <<EOL
|
|
||||||
domain
|
|
||||||
footer
|
|
||||||
metas
|
|
||||||
navbar
|
|
||||||
sidebar
|
|
||||||
sitemap
|
|
||||||
EOL
|
|
||||||
}
|
|
||||||
|
|
||||||
# Targets to NOT activate --force
|
|
||||||
#--------------------------------
|
|
||||||
_tyto_targets_not_options() {
|
|
||||||
grep -F -q -x "$1" <<EOL
|
|
||||||
added
|
|
||||||
again
|
|
||||||
domain
|
|
||||||
footer
|
|
||||||
metas
|
|
||||||
navbar
|
|
||||||
sidebar
|
|
||||||
stats
|
|
||||||
template
|
|
||||||
updated
|
|
||||||
EOL
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#=================#
|
|
||||||
# Options section #
|
|
||||||
#=================#============================================================
|
|
||||||
_tyto_options() {
|
|
||||||
cat <<EOL
|
|
||||||
--static
|
|
||||||
EOL
|
|
||||||
}
|
|
||||||
|
|
||||||
# Only with [publish template]
|
|
||||||
_tyto_options_pt() {
|
|
||||||
cat <<EOL
|
|
||||||
--no-mods
|
|
||||||
EOL
|
|
||||||
}
|
|
||||||
|
|
||||||
#=====================#
|
|
||||||
# Main autocompletion #
|
|
||||||
#=====================#========================================================
|
|
||||||
_tyto_completions() {
|
|
||||||
local cur
|
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
|
||||||
|
|
||||||
case $COMP_CWORD in
|
|
||||||
|
|
||||||
# Actions
|
|
||||||
1)
|
|
||||||
COMPREPLY=( $(compgen -W "$(_tyto_actions)" -- ${cur}) )
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
|
|
||||||
# Targets
|
|
||||||
2)
|
|
||||||
local prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
||||||
|
|
||||||
# With action "new"
|
|
||||||
if [ "$prev" == "new" ];then
|
|
||||||
COMPREPLY=( $(compgen -W "$(_tyto_targets_new)" -- ${cur}) )
|
|
||||||
return 0
|
|
||||||
|
|
||||||
elif [ "$prev" == "quick-pub" ] ||
|
|
||||||
[ "$prev" == "preview" ];then
|
|
||||||
COMPREPLY=( $(compgen -W "$(_tyto_targets_qp)" -- ${cur}) )
|
|
||||||
return 0
|
|
||||||
|
|
||||||
elif [ "$prev" == "force-wip" ];then
|
|
||||||
COMPREPLY=( $(compgen -W "$(_tyto_targets_qp)" -- ${cur}) )
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# With action "edit"
|
|
||||||
elif _tyto_actions_edits "$prev";then
|
|
||||||
COMPREPLY=( $(compgen -W "$(_tyto_targets_edits)" -- ${cur}) )
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# With action "show"
|
|
||||||
elif _tyto_actions_shows "$prev";then
|
|
||||||
COMPREPLY=( $(compgen -W "$(_tyto_targets_shows)" -- ${cur}) )
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# With wip/publish only
|
|
||||||
elif _tyto_actions_wp "$prev";then
|
|
||||||
COMPREPLY=( $(compgen -W "$(_tyto_targets_wp)" -- ${cur}) )
|
|
||||||
return 0
|
|
||||||
|
|
||||||
# When action is alone
|
|
||||||
elif ! _tyto_actions_only "$prev";then
|
|
||||||
COMPREPLY=( $(compgen -W "$(_tyto_targets)" -- ${cur}) )
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
# Optionss
|
|
||||||
3)
|
|
||||||
local prev1="${COMP_WORDS[COMP_CWORD-1]}"
|
|
||||||
local prev2="${COMP_WORDS[COMP_CWORD-2]}"
|
|
||||||
|
|
||||||
if [ "$prev2" == "wip" ];then
|
|
||||||
if ! _tyto_targets_not_options "$prev1";then
|
|
||||||
COMPREPLY=( $(compgen -W "$(_tyto_options)" -- ${cur}) )
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Only with [publish template]
|
|
||||||
elif [ "$prev2" == "publish" ] && \
|
|
||||||
[ "$prev1" == "template" ];then
|
|
||||||
COMPREPLY=( $(compgen -W "$(_tyto_options_pt)" -- ${cur}) )
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
complete -F _tyto_completions 'tyto'
|
|
|
@ -1,14 +0,0 @@
|
||||||
# Changelog
|
|
||||||
|
|
||||||
Tyto - Littérateur
|
|
||||||
- Repository: https://git.a-lec.org/echolib/tyto-litterateur
|
|
||||||
- Issues: https://git.a-lec.org/echolib/tyto-litterateur/-/issues
|
|
||||||
- Changelog: https://git.a-lec.org/echolib/tyto-litterateur/-/blob/master/CHANGELOG.md
|
|
||||||
- License: https://git.a-lec.org/echolib/tyto-litterateur/-/blob/master/LICENSE
|
|
||||||
- Documentation: https://tyto.echolib.re
|
|
||||||
|
|
||||||
## [1.0.0]
|
|
||||||
- (2023.05.09)
|
|
||||||
- - Official first public release
|
|
||||||
|
|
||||||
|
|
|
@ -1,661 +0,0 @@
|
||||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
||||||
Version 3, 19 November 2007
|
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The GNU Affero General Public License is a free, copyleft license for
|
|
||||||
software and other kinds of works, specifically designed to ensure
|
|
||||||
cooperation with the community in the case of network server software.
|
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
|
||||||
to take away your freedom to share and change the works. By contrast,
|
|
||||||
our General Public Licenses are intended to guarantee your freedom to
|
|
||||||
share and change all versions of a program--to make sure it remains free
|
|
||||||
software for all its users.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
them if you wish), that you receive source code or can get it if you
|
|
||||||
want it, that you can change the software or use pieces of it in new
|
|
||||||
free programs, and that you know you can do these things.
|
|
||||||
|
|
||||||
Developers that use our General Public Licenses protect your rights
|
|
||||||
with two steps: (1) assert copyright on the software, and (2) offer
|
|
||||||
you this License which gives you legal permission to copy, distribute
|
|
||||||
and/or modify the software.
|
|
||||||
|
|
||||||
A secondary benefit of defending all users' freedom is that
|
|
||||||
improvements made in alternate versions of the program, if they
|
|
||||||
receive widespread use, become available for other developers to
|
|
||||||
incorporate. Many developers of free software are heartened and
|
|
||||||
encouraged by the resulting cooperation. However, in the case of
|
|
||||||
software used on network servers, this result may fail to come about.
|
|
||||||
The GNU General Public License permits making a modified version and
|
|
||||||
letting the public access it on a server without ever releasing its
|
|
||||||
source code to the public.
|
|
||||||
|
|
||||||
The GNU Affero General Public License is designed specifically to
|
|
||||||
ensure that, in such cases, the modified source code becomes available
|
|
||||||
to the community. It requires the operator of a network server to
|
|
||||||
provide the source code of the modified version running there to the
|
|
||||||
users of that server. Therefore, public use of a modified version, on
|
|
||||||
a publicly accessible server, gives the public access to the source
|
|
||||||
code of the modified version.
|
|
||||||
|
|
||||||
An older license, called the Affero General Public License and
|
|
||||||
published by Affero, was designed to accomplish similar goals. This is
|
|
||||||
a different license, not a version of the Affero GPL, but Affero has
|
|
||||||
released a new version of the Affero GPL which permits relicensing under
|
|
||||||
this license.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
0. Definitions.
|
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
|
||||||
works, such as semiconductor masks.
|
|
||||||
|
|
||||||
"The Program" refers to any copyrightable work licensed under this
|
|
||||||
License. Each licensee is addressed as "you". "Licensees" and
|
|
||||||
"recipients" may be individuals or organizations.
|
|
||||||
|
|
||||||
To "modify" a work means to copy from or adapt all or part of the work
|
|
||||||
in a fashion requiring copyright permission, other than the making of an
|
|
||||||
exact copy. The resulting work is called a "modified version" of the
|
|
||||||
earlier work or a work "based on" the earlier work.
|
|
||||||
|
|
||||||
A "covered work" means either the unmodified Program or a work based
|
|
||||||
on the Program.
|
|
||||||
|
|
||||||
To "propagate" a work means to do anything with it that, without
|
|
||||||
permission, would make you directly or secondarily liable for
|
|
||||||
infringement under applicable copyright law, except executing it on a
|
|
||||||
computer or modifying a private copy. Propagation includes copying,
|
|
||||||
distribution (with or without modification), making available to the
|
|
||||||
public, and in some countries other activities as well.
|
|
||||||
|
|
||||||
To "convey" a work means any kind of propagation that enables other
|
|
||||||
parties to make or receive copies. Mere interaction with a user through
|
|
||||||
a computer network, with no transfer of a copy, is not conveying.
|
|
||||||
|
|
||||||
An interactive user interface displays "Appropriate Legal Notices"
|
|
||||||
to the extent that it includes a convenient and prominently visible
|
|
||||||
feature that (1) displays an appropriate copyright notice, and (2)
|
|
||||||
tells the user that there is no warranty for the work (except to the
|
|
||||||
extent that warranties are provided), that licensees may convey the
|
|
||||||
work under this License, and how to view a copy of this License. If
|
|
||||||
the interface presents a list of user commands or options, such as a
|
|
||||||
menu, a prominent item in the list meets this criterion.
|
|
||||||
|
|
||||||
1. Source Code.
|
|
||||||
|
|
||||||
The "source code" for a work means the preferred form of the work
|
|
||||||
for making modifications to it. "Object code" means any non-source
|
|
||||||
form of a work.
|
|
||||||
|
|
||||||
A "Standard Interface" means an interface that either is an official
|
|
||||||
standard defined by a recognized standards body, or, in the case of
|
|
||||||
interfaces specified for a particular programming language, one that
|
|
||||||
is widely used among developers working in that language.
|
|
||||||
|
|
||||||
The "System Libraries" of an executable work include anything, other
|
|
||||||
than the work as a whole, that (a) is included in the normal form of
|
|
||||||
packaging a Major Component, but which is not part of that Major
|
|
||||||
Component, and (b) serves only to enable use of the work with that
|
|
||||||
Major Component, or to implement a Standard Interface for which an
|
|
||||||
implementation is available to the public in source code form. A
|
|
||||||
"Major Component", in this context, means a major essential component
|
|
||||||
(kernel, window system, and so on) of the specific operating system
|
|
||||||
(if any) on which the executable work runs, or a compiler used to
|
|
||||||
produce the work, or an object code interpreter used to run it.
|
|
||||||
|
|
||||||
The "Corresponding Source" for a work in object code form means all
|
|
||||||
the source code needed to generate, install, and (for an executable
|
|
||||||
work) run the object code and to modify the work, including scripts to
|
|
||||||
control those activities. However, it does not include the work's
|
|
||||||
System Libraries, or general-purpose tools or generally available free
|
|
||||||
programs which are used unmodified in performing those activities but
|
|
||||||
which are not part of the work. For example, Corresponding Source
|
|
||||||
includes interface definition files associated with source files for
|
|
||||||
the work, and the source code for shared libraries and dynamically
|
|
||||||
linked subprograms that the work is specifically designed to require,
|
|
||||||
such as by intimate data communication or control flow between those
|
|
||||||
subprograms and other parts of the work.
|
|
||||||
|
|
||||||
The Corresponding Source need not include anything that users
|
|
||||||
can regenerate automatically from other parts of the Corresponding
|
|
||||||
Source.
|
|
||||||
|
|
||||||
The Corresponding Source for a work in source code form is that
|
|
||||||
same work.
|
|
||||||
|
|
||||||
2. Basic Permissions.
|
|
||||||
|
|
||||||
All rights granted under this License are granted for the term of
|
|
||||||
copyright on the Program, and are irrevocable provided the stated
|
|
||||||
conditions are met. This License explicitly affirms your unlimited
|
|
||||||
permission to run the unmodified Program. The output from running a
|
|
||||||
covered work is covered by this License only if the output, given its
|
|
||||||
content, constitutes a covered work. This License acknowledges your
|
|
||||||
rights of fair use or other equivalent, as provided by copyright law.
|
|
||||||
|
|
||||||
You may make, run and propagate covered works that you do not
|
|
||||||
convey, without conditions so long as your license otherwise remains
|
|
||||||
in force. You may convey covered works to others for the sole purpose
|
|
||||||
of having them make modifications exclusively for you, or provide you
|
|
||||||
with facilities for running those works, provided that you comply with
|
|
||||||
the terms of this License in conveying all material for which you do
|
|
||||||
not control copyright. Those thus making or running the covered works
|
|
||||||
for you must do so exclusively on your behalf, under your direction
|
|
||||||
and control, on terms that prohibit them from making any copies of
|
|
||||||
your copyrighted material outside their relationship with you.
|
|
||||||
|
|
||||||
Conveying under any other circumstances is permitted solely under
|
|
||||||
the conditions stated below. Sublicensing is not allowed; section 10
|
|
||||||
makes it unnecessary.
|
|
||||||
|
|
||||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
|
||||||
|
|
||||||
No covered work shall be deemed part of an effective technological
|
|
||||||
measure under any applicable law fulfilling obligations under article
|
|
||||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
|
||||||
similar laws prohibiting or restricting circumvention of such
|
|
||||||
measures.
|
|
||||||
|
|
||||||
When you convey a covered work, you waive any legal power to forbid
|
|
||||||
circumvention of technological measures to the extent such circumvention
|
|
||||||
is effected by exercising rights under this License with respect to
|
|
||||||
the covered work, and you disclaim any intention to limit operation or
|
|
||||||
modification of the work as a means of enforcing, against the work's
|
|
||||||
users, your or third parties' legal rights to forbid circumvention of
|
|
||||||
technological measures.
|
|
||||||
|
|
||||||
4. Conveying Verbatim Copies.
|
|
||||||
|
|
||||||
You may convey verbatim copies of the Program's source code as you
|
|
||||||
receive it, in any medium, provided that you conspicuously and
|
|
||||||
appropriately publish on each copy an appropriate copyright notice;
|
|
||||||
keep intact all notices stating that this License and any
|
|
||||||
non-permissive terms added in accord with section 7 apply to the code;
|
|
||||||
keep intact all notices of the absence of any warranty; and give all
|
|
||||||
recipients a copy of this License along with the Program.
|
|
||||||
|
|
||||||
You may charge any price or no price for each copy that you convey,
|
|
||||||
and you may offer support or warranty protection for a fee.
|
|
||||||
|
|
||||||
5. Conveying Modified Source Versions.
|
|
||||||
|
|
||||||
You may convey a work based on the Program, or the modifications to
|
|
||||||
produce it from the Program, in the form of source code under the
|
|
||||||
terms of section 4, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) The work must carry prominent notices stating that you modified
|
|
||||||
it, and giving a relevant date.
|
|
||||||
|
|
||||||
b) The work must carry prominent notices stating that it is
|
|
||||||
released under this License and any conditions added under section
|
|
||||||
7. This requirement modifies the requirement in section 4 to
|
|
||||||
"keep intact all notices".
|
|
||||||
|
|
||||||
c) You must license the entire work, as a whole, under this
|
|
||||||
License to anyone who comes into possession of a copy. This
|
|
||||||
License will therefore apply, along with any applicable section 7
|
|
||||||
additional terms, to the whole of the work, and all its parts,
|
|
||||||
regardless of how they are packaged. This License gives no
|
|
||||||
permission to license the work in any other way, but it does not
|
|
||||||
invalidate such permission if you have separately received it.
|
|
||||||
|
|
||||||
d) If the work has interactive user interfaces, each must display
|
|
||||||
Appropriate Legal Notices; however, if the Program has interactive
|
|
||||||
interfaces that do not display Appropriate Legal Notices, your
|
|
||||||
work need not make them do so.
|
|
||||||
|
|
||||||
A compilation of a covered work with other separate and independent
|
|
||||||
works, which are not by their nature extensions of the covered work,
|
|
||||||
and which are not combined with it such as to form a larger program,
|
|
||||||
in or on a volume of a storage or distribution medium, is called an
|
|
||||||
"aggregate" if the compilation and its resulting copyright are not
|
|
||||||
used to limit the access or legal rights of the compilation's users
|
|
||||||
beyond what the individual works permit. Inclusion of a covered work
|
|
||||||
in an aggregate does not cause this License to apply to the other
|
|
||||||
parts of the aggregate.
|
|
||||||
|
|
||||||
6. Conveying Non-Source Forms.
|
|
||||||
|
|
||||||
You may convey a covered work in object code form under the terms
|
|
||||||
of sections 4 and 5, provided that you also convey the
|
|
||||||
machine-readable Corresponding Source under the terms of this License,
|
|
||||||
in one of these ways:
|
|
||||||
|
|
||||||
a) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by the
|
|
||||||
Corresponding Source fixed on a durable physical medium
|
|
||||||
customarily used for software interchange.
|
|
||||||
|
|
||||||
b) Convey the object code in, or embodied in, a physical product
|
|
||||||
(including a physical distribution medium), accompanied by a
|
|
||||||
written offer, valid for at least three years and valid for as
|
|
||||||
long as you offer spare parts or customer support for that product
|
|
||||||
model, to give anyone who possesses the object code either (1) a
|
|
||||||
copy of the Corresponding Source for all the software in the
|
|
||||||
product that is covered by this License, on a durable physical
|
|
||||||
medium customarily used for software interchange, for a price no
|
|
||||||
more than your reasonable cost of physically performing this
|
|
||||||
conveying of source, or (2) access to copy the
|
|
||||||
Corresponding Source from a network server at no charge.
|
|
||||||
|
|
||||||
c) Convey individual copies of the object code with a copy of the
|
|
||||||
written offer to provide the Corresponding Source. This
|
|
||||||
alternative is allowed only occasionally and noncommercially, and
|
|
||||||
only if you received the object code with such an offer, in accord
|
|
||||||
with subsection 6b.
|
|
||||||
|
|
||||||
d) Convey the object code by offering access from a designated
|
|
||||||
place (gratis or for a charge), and offer equivalent access to the
|
|
||||||
Corresponding Source in the same way through the same place at no
|
|
||||||
further charge. You need not require recipients to copy the
|
|
||||||
Corresponding Source along with the object code. If the place to
|
|
||||||
copy the object code is a network server, the Corresponding Source
|
|
||||||
may be on a different server (operated by you or a third party)
|
|
||||||
that supports equivalent copying facilities, provided you maintain
|
|
||||||
clear directions next to the object code saying where to find the
|
|
||||||
Corresponding Source. Regardless of what server hosts the
|
|
||||||
Corresponding Source, you remain obligated to ensure that it is
|
|
||||||
available for as long as needed to satisfy these requirements.
|
|
||||||
|
|
||||||
e) Convey the object code using peer-to-peer transmission, provided
|
|
||||||
you inform other peers where the object code and Corresponding
|
|
||||||
Source of the work are being offered to the general public at no
|
|
||||||
charge under subsection 6d.
|
|
||||||
|
|
||||||
A separable portion of the object code, whose source code is excluded
|
|
||||||
from the Corresponding Source as a System Library, need not be
|
|
||||||
included in conveying the object code work.
|
|
||||||
|
|
||||||
A "User Product" is either (1) a "consumer product", which means any
|
|
||||||
tangible personal property which is normally used for personal, family,
|
|
||||||
or household purposes, or (2) anything designed or sold for incorporation
|
|
||||||
into a dwelling. In determining whether a product is a consumer product,
|
|
||||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
|
||||||
product received by a particular user, "normally used" refers to a
|
|
||||||
typical or common use of that class of product, regardless of the status
|
|
||||||
of the particular user or of the way in which the particular user
|
|
||||||
actually uses, or expects or is expected to use, the product. A product
|
|
||||||
is a consumer product regardless of whether the product has substantial
|
|
||||||
commercial, industrial or non-consumer uses, unless such uses represent
|
|
||||||
the only significant mode of use of the product.
|
|
||||||
|
|
||||||
"Installation Information" for a User Product means any methods,
|
|
||||||
procedures, authorization keys, or other information required to install
|
|
||||||
and execute modified versions of a covered work in that User Product from
|
|
||||||
a modified version of its Corresponding Source. The information must
|
|
||||||
suffice to ensure that the continued functioning of the modified object
|
|
||||||
code is in no case prevented or interfered with solely because
|
|
||||||
modification has been made.
|
|
||||||
|
|
||||||
If you convey an object code work under this section in, or with, or
|
|
||||||
specifically for use in, a User Product, and the conveying occurs as
|
|
||||||
part of a transaction in which the right of possession and use of the
|
|
||||||
User Product is transferred to the recipient in perpetuity or for a
|
|
||||||
fixed term (regardless of how the transaction is characterized), the
|
|
||||||
Corresponding Source conveyed under this section must be accompanied
|
|
||||||
by the Installation Information. But this requirement does not apply
|
|
||||||
if neither you nor any third party retains the ability to install
|
|
||||||
modified object code on the User Product (for example, the work has
|
|
||||||
been installed in ROM).
|
|
||||||
|
|
||||||
The requirement to provide Installation Information does not include a
|
|
||||||
requirement to continue to provide support service, warranty, or updates
|
|
||||||
for a work that has been modified or installed by the recipient, or for
|
|
||||||
the User Product in which it has been modified or installed. Access to a
|
|
||||||
network may be denied when the modification itself materially and
|
|
||||||
adversely affects the operation of the network or violates the rules and
|
|
||||||
protocols for communication across the network.
|
|
||||||
|
|
||||||
Corresponding Source conveyed, and Installation Information provided,
|
|
||||||
in accord with this section must be in a format that is publicly
|
|
||||||
documented (and with an implementation available to the public in
|
|
||||||
source code form), and must require no special password or key for
|
|
||||||
unpacking, reading or copying.
|
|
||||||
|
|
||||||
7. Additional Terms.
|
|
||||||
|
|
||||||
"Additional permissions" are terms that supplement the terms of this
|
|
||||||
License by making exceptions from one or more of its conditions.
|
|
||||||
Additional permissions that are applicable to the entire Program shall
|
|
||||||
be treated as though they were included in this License, to the extent
|
|
||||||
that they are valid under applicable law. If additional permissions
|
|
||||||
apply only to part of the Program, that part may be used separately
|
|
||||||
under those permissions, but the entire Program remains governed by
|
|
||||||
this License without regard to the additional permissions.
|
|
||||||
|
|
||||||
When you convey a copy of a covered work, you may at your option
|
|
||||||
remove any additional permissions from that copy, or from any part of
|
|
||||||
it. (Additional permissions may be written to require their own
|
|
||||||
removal in certain cases when you modify the work.) You may place
|
|
||||||
additional permissions on material, added by you to a covered work,
|
|
||||||
for which you have or can give appropriate copyright permission.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, for material you
|
|
||||||
add to a covered work, you may (if authorized by the copyright holders of
|
|
||||||
that material) supplement the terms of this License with terms:
|
|
||||||
|
|
||||||
a) Disclaiming warranty or limiting liability differently from the
|
|
||||||
terms of sections 15 and 16 of this License; or
|
|
||||||
|
|
||||||
b) Requiring preservation of specified reasonable legal notices or
|
|
||||||
author attributions in that material or in the Appropriate Legal
|
|
||||||
Notices displayed by works containing it; or
|
|
||||||
|
|
||||||
c) Prohibiting misrepresentation of the origin of that material, or
|
|
||||||
requiring that modified versions of such material be marked in
|
|
||||||
reasonable ways as different from the original version; or
|
|
||||||
|
|
||||||
d) Limiting the use for publicity purposes of names of licensors or
|
|
||||||
authors of the material; or
|
|
||||||
|
|
||||||
e) Declining to grant rights under trademark law for use of some
|
|
||||||
trade names, trademarks, or service marks; or
|
|
||||||
|
|
||||||
f) Requiring indemnification of licensors and authors of that
|
|
||||||
material by anyone who conveys the material (or modified versions of
|
|
||||||
it) with contractual assumptions of liability to the recipient, for
|
|
||||||
any liability that these contractual assumptions directly impose on
|
|
||||||
those licensors and authors.
|
|
||||||
|
|
||||||
All other non-permissive additional terms are considered "further
|
|
||||||
restrictions" within the meaning of section 10. If the Program as you
|
|
||||||
received it, or any part of it, contains a notice stating that it is
|
|
||||||
governed by this License along with a term that is a further
|
|
||||||
restriction, you may remove that term. If a license document contains
|
|
||||||
a further restriction but permits relicensing or conveying under this
|
|
||||||
License, you may add to a covered work material governed by the terms
|
|
||||||
of that license document, provided that the further restriction does
|
|
||||||
not survive such relicensing or conveying.
|
|
||||||
|
|
||||||
If you add terms to a covered work in accord with this section, you
|
|
||||||
must place, in the relevant source files, a statement of the
|
|
||||||
additional terms that apply to those files, or a notice indicating
|
|
||||||
where to find the applicable terms.
|
|
||||||
|
|
||||||
Additional terms, permissive or non-permissive, may be stated in the
|
|
||||||
form of a separately written license, or stated as exceptions;
|
|
||||||
the above requirements apply either way.
|
|
||||||
|
|
||||||
8. Termination.
|
|
||||||
|
|
||||||
You may not propagate or modify a covered work except as expressly
|
|
||||||
provided under this License. Any attempt otherwise to propagate or
|
|
||||||
modify it is void, and will automatically terminate your rights under
|
|
||||||
this License (including any patent licenses granted under the third
|
|
||||||
paragraph of section 11).
|
|
||||||
|
|
||||||
However, if you cease all violation of this License, then your
|
|
||||||
license from a particular copyright holder is reinstated (a)
|
|
||||||
provisionally, unless and until the copyright holder explicitly and
|
|
||||||
finally terminates your license, and (b) permanently, if the copyright
|
|
||||||
holder fails to notify you of the violation by some reasonable means
|
|
||||||
prior to 60 days after the cessation.
|
|
||||||
|
|
||||||
Moreover, your license from a particular copyright holder is
|
|
||||||
reinstated permanently if the copyright holder notifies you of the
|
|
||||||
violation by some reasonable means, this is the first time you have
|
|
||||||
received notice of violation of this License (for any work) from that
|
|
||||||
copyright holder, and you cure the violation prior to 30 days after
|
|
||||||
your receipt of the notice.
|
|
||||||
|
|
||||||
Termination of your rights under this section does not terminate the
|
|
||||||
licenses of parties who have received copies or rights from you under
|
|
||||||
this License. If your rights have been terminated and not permanently
|
|
||||||
reinstated, you do not qualify to receive new licenses for the same
|
|
||||||
material under section 10.
|
|
||||||
|
|
||||||
9. Acceptance Not Required for Having Copies.
|
|
||||||
|
|
||||||
You are not required to accept this License in order to receive or
|
|
||||||
run a copy of the Program. Ancillary propagation of a covered work
|
|
||||||
occurring solely as a consequence of using peer-to-peer transmission
|
|
||||||
to receive a copy likewise does not require acceptance. However,
|
|
||||||
nothing other than this License grants you permission to propagate or
|
|
||||||
modify any covered work. These actions infringe copyright if you do
|
|
||||||
not accept this License. Therefore, by modifying or propagating a
|
|
||||||
covered work, you indicate your acceptance of this License to do so.
|
|
||||||
|
|
||||||
10. Automatic Licensing of Downstream Recipients.
|
|
||||||
|
|
||||||
Each time you convey a covered work, the recipient automatically
|
|
||||||
receives a license from the original licensors, to run, modify and
|
|
||||||
propagate that work, subject to this License. You are not responsible
|
|
||||||
for enforcing compliance by third parties with this License.
|
|
||||||
|
|
||||||
An "entity transaction" is a transaction transferring control of an
|
|
||||||
organization, or substantially all assets of one, or subdividing an
|
|
||||||
organization, or merging organizations. If propagation of a covered
|
|
||||||
work results from an entity transaction, each party to that
|
|
||||||
transaction who receives a copy of the work also receives whatever
|
|
||||||
licenses to the work the party's predecessor in interest had or could
|
|
||||||
give under the previous paragraph, plus a right to possession of the
|
|
||||||
Corresponding Source of the work from the predecessor in interest, if
|
|
||||||
the predecessor has it or can get it with reasonable efforts.
|
|
||||||
|
|
||||||
You may not impose any further restrictions on the exercise of the
|
|
||||||
rights granted or affirmed under this License. For example, you may
|
|
||||||
not impose a license fee, royalty, or other charge for exercise of
|
|
||||||
rights granted under this License, and you may not initiate litigation
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
|
||||||
any patent claim is infringed by making, using, selling, offering for
|
|
||||||
sale, or importing the Program or any portion of it.
|
|
||||||
|
|
||||||
11. Patents.
|
|
||||||
|
|
||||||
A "contributor" is a copyright holder who authorizes use under this
|
|
||||||
License of the Program or a work on which the Program is based. The
|
|
||||||
work thus licensed is called the contributor's "contributor version".
|
|
||||||
|
|
||||||
A contributor's "essential patent claims" are all patent claims
|
|
||||||
owned or controlled by the contributor, whether already acquired or
|
|
||||||
hereafter acquired, that would be infringed by some manner, permitted
|
|
||||||
by this License, of making, using, or selling its contributor version,
|
|
||||||
but do not include claims that would be infringed only as a
|
|
||||||
consequence of further modification of the contributor version. For
|
|
||||||
purposes of this definition, "control" includes the right to grant
|
|
||||||
patent sublicenses in a manner consistent with the requirements of
|
|
||||||
this License.
|
|
||||||
|
|
||||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
|
||||||
patent license under the contributor's essential patent claims, to
|
|
||||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
|
||||||
propagate the contents of its contributor version.
|
|
||||||
|
|
||||||
In the following three paragraphs, a "patent license" is any express
|
|
||||||
agreement or commitment, however denominated, not to enforce a patent
|
|
||||||
(such as an express permission to practice a patent or covenant not to
|
|
||||||
sue for patent infringement). To "grant" such a patent license to a
|
|
||||||
party means to make such an agreement or commitment not to enforce a
|
|
||||||
patent against the party.
|
|
||||||
|
|
||||||
If you convey a covered work, knowingly relying on a patent license,
|
|
||||||
and the Corresponding Source of the work is not available for anyone
|
|
||||||
to copy, free of charge and under the terms of this License, through a
|
|
||||||
publicly available network server or other readily accessible means,
|
|
||||||
then you must either (1) cause the Corresponding Source to be so
|
|
||||||
available, or (2) arrange to deprive yourself of the benefit of the
|
|
||||||
patent license for this particular work, or (3) arrange, in a manner
|
|
||||||
consistent with the requirements of this License, to extend the patent
|
|
||||||
license to downstream recipients. "Knowingly relying" means you have
|
|
||||||
actual knowledge that, but for the patent license, your conveying the
|
|
||||||
covered work in a country, or your recipient's use of the covered work
|
|
||||||
in a country, would infringe one or more identifiable patents in that
|
|
||||||
country that you have reason to believe are valid.
|
|
||||||
|
|
||||||
If, pursuant to or in connection with a single transaction or
|
|
||||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
|
||||||
covered work, and grant a patent license to some of the parties
|
|
||||||
receiving the covered work authorizing them to use, propagate, modify
|
|
||||||
or convey a specific copy of the covered work, then the patent license
|
|
||||||
you grant is automatically extended to all recipients of the covered
|
|
||||||
work and works based on it.
|
|
||||||
|
|
||||||
A patent license is "discriminatory" if it does not include within
|
|
||||||
the scope of its coverage, prohibits the exercise of, or is
|
|
||||||
conditioned on the non-exercise of one or more of the rights that are
|
|
||||||
specifically granted under this License. You may not convey a covered
|
|
||||||
work if you are a party to an arrangement with a third party that is
|
|
||||||
in the business of distributing software, under which you make payment
|
|
||||||
to the third party based on the extent of your activity of conveying
|
|
||||||
the work, and under which the third party grants, to any of the
|
|
||||||
parties who would receive the covered work from you, a discriminatory
|
|
||||||
patent license (a) in connection with copies of the covered work
|
|
||||||
conveyed by you (or copies made from those copies), or (b) primarily
|
|
||||||
for and in connection with specific products or compilations that
|
|
||||||
contain the covered work, unless you entered into that arrangement,
|
|
||||||
or that patent license was granted, prior to 28 March 2007.
|
|
||||||
|
|
||||||
Nothing in this License shall be construed as excluding or limiting
|
|
||||||
any implied license or other defenses to infringement that may
|
|
||||||
otherwise be available to you under applicable patent law.
|
|
||||||
|
|
||||||
12. No Surrender of Others' Freedom.
|
|
||||||
|
|
||||||
If conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot convey a
|
|
||||||
covered work so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you may
|
|
||||||
not convey it at all. For example, if you agree to terms that obligate you
|
|
||||||
to collect a royalty for further conveying from those to whom you convey
|
|
||||||
the Program, the only way you could satisfy both those terms and this
|
|
||||||
License would be to refrain entirely from conveying the Program.
|
|
||||||
|
|
||||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, if you modify the
|
|
||||||
Program, your modified version must prominently offer all users
|
|
||||||
interacting with it remotely through a computer network (if your version
|
|
||||||
supports such interaction) an opportunity to receive the Corresponding
|
|
||||||
Source of your version by providing access to the Corresponding Source
|
|
||||||
from a network server at no charge, through some standard or customary
|
|
||||||
means of facilitating copying of software. This Corresponding Source
|
|
||||||
shall include the Corresponding Source for any work covered by version 3
|
|
||||||
of the GNU General Public License that is incorporated pursuant to the
|
|
||||||
following paragraph.
|
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
|
||||||
permission to link or combine any covered work with a work licensed
|
|
||||||
under version 3 of the GNU General Public License into a single
|
|
||||||
combined work, and to convey the resulting work. The terms of this
|
|
||||||
License will continue to apply to the part which is the covered work,
|
|
||||||
but the work with which it is combined will remain governed by version
|
|
||||||
3 of the GNU General Public License.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
|
||||||
the GNU Affero General Public License from time to time. Such new versions
|
|
||||||
will be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
|
||||||
Program specifies that a certain numbered version of the GNU Affero General
|
|
||||||
Public License "or any later version" applies to it, you have the
|
|
||||||
option of following the terms and conditions either of that numbered
|
|
||||||
version or of any later version published by the Free Software
|
|
||||||
Foundation. If the Program does not specify a version number of the
|
|
||||||
GNU Affero General Public License, you may choose any version ever published
|
|
||||||
by the Free Software Foundation.
|
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
|
||||||
versions of the GNU Affero General Public License can be used, that proxy's
|
|
||||||
public statement of acceptance of a version permanently authorizes you
|
|
||||||
to choose that version for the Program.
|
|
||||||
|
|
||||||
Later license versions may give you additional or different
|
|
||||||
permissions. However, no additional obligations are imposed on any
|
|
||||||
author or copyright holder as a result of your choosing to follow a
|
|
||||||
later version.
|
|
||||||
|
|
||||||
15. Disclaimer of Warranty.
|
|
||||||
|
|
||||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
|
||||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
|
||||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
|
||||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
|
||||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
|
||||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
16. Limitation of Liability.
|
|
||||||
|
|
||||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
|
||||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
|
||||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
|
||||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
|
||||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
|
||||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
|
||||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGES.
|
|
||||||
|
|
||||||
17. Interpretation of Sections 15 and 16.
|
|
||||||
|
|
||||||
If the disclaimer of warranty and limitation of liability provided
|
|
||||||
above cannot be given local legal effect according to their terms,
|
|
||||||
reviewing courts shall apply local law that most closely approximates
|
|
||||||
an absolute waiver of all civil liability in connection with the
|
|
||||||
Program, unless a warranty or assumption of liability accompanies a
|
|
||||||
copy of the Program in return for a fee.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
state the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
GSL Statique Littérateur
|
|
||||||
Copyright (C) 2022 Libre en Communs / Commissions / Infrastructure
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published
|
|
||||||
by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If your software can interact with users remotely through a computer
|
|
||||||
network, you should also make sure that it provides a way for users to
|
|
||||||
get its source. For example, if your program is a web application, its
|
|
||||||
interface could display a "Source" link that leads users to an archive
|
|
||||||
of the code. There are many ways you could offer source, and different
|
|
||||||
solutions will be better for different programs; see section 13 for the
|
|
||||||
specific requirements.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
||||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
|
||||||
<https://www.gnu.org/licenses/>.
|
|
|
@ -1,53 +0,0 @@
|
||||||
# Tyto
|
|
||||||
- FR. Pour obtenir de l'aide, taper juste la commande tyto
|
|
||||||
- EN. To get help, just type tyto.
|
|
||||||
- - Doc is only in french yet, but Tyto is translated, also for your websites
|
|
||||||
|
|
||||||
## Répertoire de code du projet Tyto
|
|
||||||
https://git.a-lec.org/echolib/tyto-litterateur
|
|
||||||
|
|
||||||
## Documentation officielle
|
|
||||||
https://tyto.echolib.re (en cours de construction)
|
|
||||||
|
|
||||||
## Créer un domaine
|
|
||||||
````
|
|
||||||
mkdir -p MONDOMAIN
|
|
||||||
cd MONDOMAIN
|
|
||||||
tyto new domain URL
|
|
||||||
````
|
|
||||||
|
|
||||||
# Créer un article
|
|
||||||
https://tyto.echolib.re/%C3%A9crire/
|
|
||||||
```
|
|
||||||
cd articles/
|
|
||||||
tyto new index
|
|
||||||
tyto edit index.tyto
|
|
||||||
```
|
|
||||||
|
|
||||||
# Vérifier, prévisualiser un article
|
|
||||||
```
|
|
||||||
tyto check index.tyto
|
|
||||||
tyto wip index.tyto
|
|
||||||
```
|
|
||||||
|
|
||||||
# Les modules
|
|
||||||
https://tyto.echolib.re/usages/modules.html
|
|
||||||
|
|
||||||
La barre latérale, le menu, le pied de page et les balises génériques metas
|
|
||||||
ne seront pas visible localement sans serveur nginx.
|
|
||||||
|
|
||||||
Utiliser l'option --static avec la commande wip pour les voir. Attention,
|
|
||||||
utiliser la commande publish après avoir utilisé l'option --static sur wip
|
|
||||||
mettra en ligne la version statique de la page. Il faut donc avant la
|
|
||||||
commande publish, recommencer la commande wip sur un article sans l'option
|
|
||||||
--static pour utiliser l'include de nginx (comportement par défaut)
|
|
||||||
|
|
||||||
|
|
||||||
# Publier !
|
|
||||||
```
|
|
||||||
# La première fois, ou après mise à jour des modules ou des fichiers (logo, css...)
|
|
||||||
tyto publish template
|
|
||||||
|
|
||||||
# Mettre dans le dossier "www" officiel
|
|
||||||
tyto publish index.tyto
|
|
||||||
```
|
|
|
@ -1,224 +0,0 @@
|
||||||
/*
|
|
||||||
* All class / ID used by Tyto - Littérateur in a page
|
|
||||||
* DOMAIN MUST be changed by domain css set in configuration
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* include header to footer */
|
|
||||||
div#site_container {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Include article + sidebar */
|
|
||||||
div#article_sidebar_container {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*=====================================================================
|
|
||||||
* Header
|
|
||||||
*/
|
|
||||||
header#header_page {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Block */
|
|
||||||
div#site_logo {
|
|
||||||
}
|
|
||||||
|
|
||||||
a#site_logo_link {
|
|
||||||
}
|
|
||||||
|
|
||||||
img#site_logo_image {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Block */
|
|
||||||
div#site_infos {
|
|
||||||
}
|
|
||||||
|
|
||||||
a#site_link {
|
|
||||||
}
|
|
||||||
|
|
||||||
h1#site_title {
|
|
||||||
}
|
|
||||||
|
|
||||||
p#site_about {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*=====================================================================
|
|
||||||
* navbar
|
|
||||||
*/
|
|
||||||
nav#site_menu {
|
|
||||||
}
|
|
||||||
|
|
||||||
menu#site_menu_items {
|
|
||||||
}
|
|
||||||
|
|
||||||
li.site_menu_item {
|
|
||||||
}
|
|
||||||
|
|
||||||
a.site_menu_link {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*=====================================================================
|
|
||||||
* article
|
|
||||||
*/
|
|
||||||
article#article_main {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* article title */
|
|
||||||
h2#main_title {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Writer titles*/
|
|
||||||
h3.title_3 {
|
|
||||||
}
|
|
||||||
h4.title_4 {
|
|
||||||
}
|
|
||||||
h5.title_5 {
|
|
||||||
}
|
|
||||||
h6.title_6 {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Between every <h3-6> IF CONTENTS */
|
|
||||||
div.contents {
|
|
||||||
}
|
|
||||||
div.contents_2 {
|
|
||||||
}
|
|
||||||
div.contents_3 {
|
|
||||||
}
|
|
||||||
div.contents_4 {
|
|
||||||
}
|
|
||||||
div.contents_5 {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Default if not set in post */
|
|
||||||
p.DOMAIN {
|
|
||||||
}
|
|
||||||
|
|
||||||
br.DOMAIN {
|
|
||||||
}
|
|
||||||
|
|
||||||
a.link {
|
|
||||||
}
|
|
||||||
a.link-file {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When block quote with _cite:*/
|
|
||||||
a.figc {
|
|
||||||
}
|
|
||||||
|
|
||||||
a.anchor_link {
|
|
||||||
}
|
|
||||||
|
|
||||||
abbr.DOMAIN {
|
|
||||||
}
|
|
||||||
|
|
||||||
img.DOMAIN_image {
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.DOMAIN {
|
|
||||||
}
|
|
||||||
li.DOMAIN {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Words tags*/
|
|
||||||
code.icode {
|
|
||||||
}
|
|
||||||
strong.DOMAIN {
|
|
||||||
}
|
|
||||||
b.DOMAIN {
|
|
||||||
}
|
|
||||||
em.DOMAIN{
|
|
||||||
}
|
|
||||||
i.DOMAIN {
|
|
||||||
}
|
|
||||||
del.DOMAIN {
|
|
||||||
}
|
|
||||||
u.DOMAIN {
|
|
||||||
}
|
|
||||||
cite.DOMAIN {
|
|
||||||
}
|
|
||||||
span.custom {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Block-code */
|
|
||||||
code.DOMAIN {
|
|
||||||
}
|
|
||||||
pre.bcode {
|
|
||||||
}
|
|
||||||
p.bcode {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* section for author and date */
|
|
||||||
div#article_infos {
|
|
||||||
}
|
|
||||||
span#article_author {
|
|
||||||
}
|
|
||||||
span#article_pub {
|
|
||||||
}
|
|
||||||
span#article_code {
|
|
||||||
}
|
|
||||||
a#article_code_link {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Sitemap */
|
|
||||||
ul.sitemap {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*=====================================================================
|
|
||||||
* sidebar
|
|
||||||
*/
|
|
||||||
|
|
||||||
aside#sidebar {
|
|
||||||
}
|
|
||||||
h2#sidebar_title {
|
|
||||||
}
|
|
||||||
ul#sidebar_list {
|
|
||||||
}
|
|
||||||
li.sidebar_item {
|
|
||||||
}
|
|
||||||
a.sidebar_item_link {
|
|
||||||
}
|
|
||||||
h3.sidebar_item_title {
|
|
||||||
}
|
|
||||||
p.sidebar_item_about {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*=====================================================================
|
|
||||||
* footer
|
|
||||||
*/
|
|
||||||
footer#footer_page {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* container for footer_infos + footer_references */
|
|
||||||
div#footer_container {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Block*/
|
|
||||||
div#footer_infos {
|
|
||||||
}
|
|
||||||
h2#footer_site_title {
|
|
||||||
}
|
|
||||||
p#footer_about {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Block */
|
|
||||||
div#footer_references {
|
|
||||||
}
|
|
||||||
ul.footer_items {
|
|
||||||
}
|
|
||||||
li.footer_item {
|
|
||||||
}
|
|
||||||
a.footer_item_link {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Block */
|
|
||||||
div#footer_credits {
|
|
||||||
}
|
|
||||||
p.footer_copyright {
|
|
||||||
}
|
|
||||||
p.footer_generator {
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
# Home Domain
|
|
||||||
directory = ""
|
|
||||||
database = ""
|
|
||||||
|
|
||||||
# Local user configuration
|
|
||||||
lang_sys = ""
|
|
||||||
local_user = ""
|
|
||||||
lang_logs = ""
|
|
||||||
articles_db_d = ""
|
|
||||||
|
|
||||||
# Working directories
|
|
||||||
articles_d = ""
|
|
||||||
files_d = ""
|
|
||||||
images_d = ""
|
|
||||||
modules_d = ""
|
|
||||||
|
|
||||||
# Modules files
|
|
||||||
navbar_f = ""
|
|
||||||
sidebar_f = ""
|
|
||||||
metas_f = ""
|
|
||||||
footer_f = ""
|
|
||||||
|
|
||||||
# Domain
|
|
||||||
shortname = ""
|
|
||||||
www_url = ""
|
|
||||||
wip_url = ""
|
|
||||||
|
|
||||||
# Servers directories
|
|
||||||
srv_root = "/var/www/"
|
|
||||||
srv_domain = "
|
|
||||||
srv_wip = ""
|
|
||||||
srv_wip_tpl_d = ""
|
|
||||||
srv_wip_images_d = ""
|
|
||||||
srv_wip_files_d = ""
|
|
||||||
srv_www = ""
|
|
||||||
srv_www_tpl_d = ""
|
|
||||||
srv_www_images_d = ""
|
|
||||||
srv_www_files_d = ""
|
|
||||||
|
|
||||||
# Servers files (wip)
|
|
||||||
wip_favicon_f = ""
|
|
||||||
wip_logo_f = ""
|
|
||||||
wip_css_f = ""
|
|
||||||
wip_navbar_f = ""
|
|
||||||
wip_sidebar_f = ""
|
|
||||||
wip_metas_f = ""
|
|
||||||
wip_footer_f = ""
|
|
||||||
wip_stats_f = ""
|
|
||||||
|
|
||||||
# Servers files (www)
|
|
||||||
www_favicon_f = ""
|
|
||||||
www_logo_f = ""
|
|
||||||
www_css_f = ""
|
|
||||||
www_navbar_f = ""
|
|
||||||
www_sidebar_f = ""
|
|
||||||
www_metas_f = ""
|
|
||||||
www_footer_f = ""
|
|
||||||
www_stats_f = ""
|
|
||||||
www_rss_f = ""
|
|
||||||
|
|
||||||
# Domain user's settings
|
|
||||||
favicon = "favicon.png"
|
|
||||||
logo = "logo.png"
|
|
||||||
styles = "styles.css"
|
|
||||||
rss = "rss.xml"
|
|
||||||
rss_items = 100
|
|
||||||
title = ""
|
|
||||||
date = ""
|
|
||||||
about = ""
|
|
||||||
lang_site = ""
|
|
||||||
mail = ""
|
|
||||||
tags = ""
|
|
||||||
license = "gfdl-1.3"
|
|
||||||
license_url = ""
|
|
||||||
legal_url = ""
|
|
||||||
terms_url = ""
|
|
||||||
css = "tyto"
|
|
||||||
sep = "-"
|
|
||||||
article_code = True
|
|
||||||
relme = ""
|
|
||||||
sidebar_title = ""
|
|
||||||
sidebar_items = 6
|
|
||||||
|
|
||||||
activated = False
|
|
|
@ -1,19 +1,19 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Tyto - Littérateur
|
# Tyto - Littérateur
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License
|
# it under the terms of the GNU General Public License as published by
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# License, or of the License, or (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU Affero General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
@ -26,149 +26,77 @@
|
||||||
#-------------------------
|
#-------------------------
|
||||||
# Funny Stats Project
|
# Funny Stats Project
|
||||||
#-------------------------
|
#-------------------------
|
||||||
# file lines : 174
|
# file lines :
|
||||||
# file comments : 29
|
# file comments :
|
||||||
# file functions: 2
|
# file functions:
|
||||||
# file program : 135
|
# file program :
|
||||||
#--------------------------
|
#--------------------------
|
||||||
|
|
||||||
|
import sys
|
||||||
import os, sys
|
import langs, tyto, debug, help, new, check, userset, show
|
||||||
import infos
|
|
||||||
|
|
||||||
try:
|
|
||||||
action
|
|
||||||
target
|
|
||||||
|
|
||||||
except:
|
|
||||||
|
|
||||||
# Arguments from command line
|
|
||||||
# tyto [action] [target]
|
|
||||||
#----------------------------
|
|
||||||
actions = \
|
|
||||||
(
|
|
||||||
'check',
|
|
||||||
'edit',
|
|
||||||
'edit-db',
|
|
||||||
'edit-wip',
|
|
||||||
'edit-www',
|
|
||||||
'force-wip',
|
|
||||||
'new',
|
|
||||||
'preview',
|
|
||||||
'publish',
|
|
||||||
'quick-pub',
|
|
||||||
'show',
|
|
||||||
'show-db',
|
|
||||||
'show-wip',
|
|
||||||
'show-www',
|
|
||||||
'status',
|
|
||||||
'wip',
|
|
||||||
)
|
|
||||||
|
|
||||||
quicks = \
|
|
||||||
(
|
|
||||||
'force-wip',
|
|
||||||
'quick-pub',
|
|
||||||
)
|
|
||||||
|
|
||||||
options = \
|
|
||||||
(
|
|
||||||
'--static',
|
|
||||||
)
|
|
||||||
|
|
||||||
pass_actions = ('new')
|
|
||||||
|
|
||||||
# Actions that needs to check for article's database
|
|
||||||
pass_db = \
|
|
||||||
(
|
|
||||||
'check',
|
|
||||||
'edit',
|
|
||||||
'edit-db',
|
|
||||||
'edit-wip',
|
|
||||||
'edit-www',
|
|
||||||
'force-wip',
|
|
||||||
'publish',
|
|
||||||
'preview',
|
|
||||||
'quick-pub',
|
|
||||||
'show',
|
|
||||||
'show-about',
|
|
||||||
'show-db',
|
|
||||||
'show-wip',
|
|
||||||
'show-www',
|
|
||||||
'status',
|
|
||||||
'wip',
|
|
||||||
)
|
|
||||||
|
|
||||||
pass_targets = \
|
|
||||||
(
|
|
||||||
'added',
|
|
||||||
'again',
|
|
||||||
'updated',
|
|
||||||
'domain',
|
|
||||||
'footer',
|
|
||||||
'metas',
|
|
||||||
'navbar',
|
|
||||||
'sidebar',
|
|
||||||
'sitemap',
|
|
||||||
'stats',
|
|
||||||
'template'
|
|
||||||
)
|
|
||||||
|
|
||||||
pass_status = \
|
|
||||||
(
|
|
||||||
'domain',
|
|
||||||
)
|
|
||||||
|
|
||||||
multi_chk = \
|
|
||||||
(
|
|
||||||
'added',
|
|
||||||
'again',
|
|
||||||
'updated'
|
|
||||||
)
|
|
||||||
|
|
||||||
helps = \
|
|
||||||
(
|
|
||||||
'domains',
|
|
||||||
'version',
|
|
||||||
'help'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# action
|
#==================#
|
||||||
#-------
|
# Action Arguments #
|
||||||
|
#------------------#
|
||||||
|
def get_action():
|
||||||
|
global action
|
||||||
try: action = sys.argv[1]
|
try: action = sys.argv[1]
|
||||||
except: action = ''
|
except: action = ""
|
||||||
|
|
||||||
act_err = False
|
|
||||||
|
|
||||||
# With no argument, show help
|
|
||||||
if not action:
|
|
||||||
infos.tyto('full')
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
elif action in helps:
|
|
||||||
infos.tyto(action)
|
|
||||||
|
|
||||||
# Unused argument [action]
|
|
||||||
elif not action in actions:
|
|
||||||
act_err = True
|
|
||||||
|
|
||||||
|
|
||||||
# target
|
|
||||||
#-------
|
|
||||||
try:
|
|
||||||
target = sys.argv[2]
|
|
||||||
except:
|
|
||||||
infos.tyto('full')
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
# options
|
#==================#
|
||||||
try: option = sys.argv[3]
|
# Target arguments #
|
||||||
except: option = ''
|
#------------------#
|
||||||
|
def get_target():
|
||||||
|
global target
|
||||||
|
try: target = sys.argv[2]
|
||||||
|
except: target = ""
|
||||||
|
|
||||||
# Set action and target for binary
|
|
||||||
def set_action():
|
|
||||||
return(action)
|
|
||||||
|
|
||||||
def set_target():
|
#================================#
|
||||||
return(target)
|
# Searching options in arguments #
|
||||||
|
#--------------------------------#
|
||||||
|
def get_options():
|
||||||
|
global dlogs, force, erron
|
||||||
|
|
||||||
|
dlogs = force = erron = False
|
||||||
|
for arg in range(1, len(sys.argv)):
|
||||||
|
if sys.argv[arg] in tyto.debug_options: dlogs = True
|
||||||
|
if sys.argv[arg] in tyto.force_options: force = True
|
||||||
|
if sys.argv[arg] in tyto.debug_errors: erron = True
|
||||||
|
|
||||||
|
|
||||||
|
#===========#
|
||||||
|
# Show logs #
|
||||||
|
#-----------#
|
||||||
|
def valid_action():
|
||||||
|
global action
|
||||||
|
if not action in tyto.actions:
|
||||||
|
debug.out(1, "[action]", action, dlogs,2, False)
|
||||||
|
action = "help"
|
||||||
|
|
||||||
|
|
||||||
|
#==============#
|
||||||
|
# Start action #
|
||||||
|
#--------------#
|
||||||
|
def start_process():
|
||||||
|
# Set Lang logs
|
||||||
|
langs.load_logs_lang()
|
||||||
|
|
||||||
|
get_options()
|
||||||
|
get_action()
|
||||||
|
get_target()
|
||||||
|
valid_action()
|
||||||
|
|
||||||
|
do = {
|
||||||
|
"help" : help.show,
|
||||||
|
"check" : check.manage,
|
||||||
|
"new" : new.manage,
|
||||||
|
"set" : userset.manage,
|
||||||
|
"show" : show.manage,
|
||||||
|
}
|
||||||
|
|
||||||
|
do[action](action, target)
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,241 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Tyto - Littérateur
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib@dismail.de>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License
|
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# XMPP: echolib (im@echolib.re)
|
|
||||||
#
|
|
||||||
# Description: Manage 'creators' argument.
|
|
||||||
# Create articles
|
|
||||||
# File: /var/lib/tyto/program/creators.py
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#-------------------------
|
|
||||||
# Funny Stats Project
|
|
||||||
#-------------------------
|
|
||||||
# file lines : 241
|
|
||||||
# file comments : 41
|
|
||||||
# file functions: 3
|
|
||||||
# file program : 182
|
|
||||||
#--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
import os, importlib, datetime, subprocess
|
|
||||||
import args, dom, db, langs, tyto, check, wip, logs
|
|
||||||
|
|
||||||
|
|
||||||
#========================#
|
|
||||||
# Manage action [create] #
|
|
||||||
#------------------------#
|
|
||||||
def manage(target):
|
|
||||||
target = args.target
|
|
||||||
|
|
||||||
creators = {
|
|
||||||
"sitemap" : create_sitemap,
|
|
||||||
}
|
|
||||||
|
|
||||||
try: creators[target](target)
|
|
||||||
except: logs.out("28", "%s + %s"%(args.action, args.target), True)
|
|
||||||
|
|
||||||
|
|
||||||
#=====================#
|
|
||||||
# Set and return date #
|
|
||||||
#---------------------#
|
|
||||||
def nowdate():
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
return(now.strftime('%Y-%m-%d'))
|
|
||||||
|
|
||||||
|
|
||||||
#============================#
|
|
||||||
# Create sitemap.tyto file #
|
|
||||||
# Then check it, and wip it #
|
|
||||||
# ! sitemap is the "www" one #
|
|
||||||
# seen in 'wip' server #
|
|
||||||
#----------------------------#
|
|
||||||
def create_sitemap(target):
|
|
||||||
dom.valid()
|
|
||||||
|
|
||||||
# Define sitemap.tyto
|
|
||||||
sitemap_tyto = \
|
|
||||||
'# %s Tyto - Littérateur [tyto new sitemap]\n'%langs.site.sitemap_gen + \
|
|
||||||
'# NoSitemap\n' + \
|
|
||||||
'title: %s (%s %s)\n'%(langs.site.sitemap_t, '%s', langs.site.links) + \
|
|
||||||
'about: %s Tyto - Littérateur\n'%langs.site.sitemap_gen + \
|
|
||||||
'author: Tyto\n' + \
|
|
||||||
'tags: sitemap\n' + \
|
|
||||||
'date: %s\n'%nowdate() + \
|
|
||||||
'\n' + \
|
|
||||||
'%s\n' + \
|
|
||||||
'-----\n' + \
|
|
||||||
'\n' + \
|
|
||||||
'%s\n' + \
|
|
||||||
'|\n' + \
|
|
||||||
'<hr class="hr">\n' + \
|
|
||||||
'|\n' + \
|
|
||||||
'\n' + \
|
|
||||||
'%s\n'
|
|
||||||
|
|
||||||
tab = 8
|
|
||||||
uri_dir_set = ""
|
|
||||||
|
|
||||||
# Contents in article's Header
|
|
||||||
links = ""
|
|
||||||
|
|
||||||
# Index of all links in article
|
|
||||||
index_l = '-( index\n= <a href="#index">/</a>'
|
|
||||||
|
|
||||||
# All links in sitemap
|
|
||||||
contents = '-( sitemap\n= / <z id="index"></a>'
|
|
||||||
|
|
||||||
# Not real articles folder
|
|
||||||
forbid_dir = (
|
|
||||||
dom.files_d,
|
|
||||||
dom.images_d,
|
|
||||||
dom.modules_d
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get all .tyto files from domain
|
|
||||||
nbr_files = 0
|
|
||||||
for r, dirs, files in os.walk(os.getcwd()):
|
|
||||||
if r.startswith(forbid_dir):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Take only .tyto files
|
|
||||||
for f in files:
|
|
||||||
if not f.endswith(".tyto"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
uri_file = r.rsplit(dom.articles_d)[1]
|
|
||||||
uri_file = os.path.join(uri_file, f)
|
|
||||||
except:
|
|
||||||
uri_file = f
|
|
||||||
|
|
||||||
uri_dir = uri_file.rsplit(f)[0]
|
|
||||||
if not uri_dir:
|
|
||||||
uri_dir = "~/"
|
|
||||||
|
|
||||||
# Try to load Article Database
|
|
||||||
args.action = "check"
|
|
||||||
args.target = uri_file
|
|
||||||
importlib.reload(db)
|
|
||||||
if not db.exists:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
db.hash_www
|
|
||||||
db.sitemap
|
|
||||||
if not db.sitemap:
|
|
||||||
continue
|
|
||||||
except:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Count
|
|
||||||
nbr_files += 1
|
|
||||||
|
|
||||||
# create defined link
|
|
||||||
if not links:
|
|
||||||
links = \
|
|
||||||
"link: %s\n%s%s\n%s%s\n"%(
|
|
||||||
db.title, tab * " ", db.short_srv, tab * " ", db.about
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
links = \
|
|
||||||
"%s\nlink: %s\n%s%s\n%s%s\n"%(
|
|
||||||
links,
|
|
||||||
db.title, tab * " ",
|
|
||||||
db.short_srv, tab * " ", db.about
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Create list link line
|
|
||||||
curr_dir = uri_dir.count("/")
|
|
||||||
root_dir = uri_dir.rsplit("/")[0]
|
|
||||||
ranc_dir = root_dir.replace(" ", "_")
|
|
||||||
|
|
||||||
|
|
||||||
try: prev_dir
|
|
||||||
except: prev_dir = curr_dir
|
|
||||||
|
|
||||||
try: name_dir
|
|
||||||
except: name_dir = root_dir
|
|
||||||
|
|
||||||
#print(":",prev_dir, name_dir, curr_dir, root_dir)
|
|
||||||
#print(": %s"%(uri_dir.rsplit("/")[int(curr_dir - 1)]))
|
|
||||||
#print(">", subdirs, uri_dir.rsplit("/"))
|
|
||||||
#print(":", prev_dir, curr_dir)
|
|
||||||
if name_dir != root_dir:
|
|
||||||
index_l = '%s\n= <a href="#%s">%s</a>'%(
|
|
||||||
index_l,
|
|
||||||
ranc_dir,
|
|
||||||
root_dir
|
|
||||||
)
|
|
||||||
contents = '%s\n%s [%s] <a id="%s"></a>'%(
|
|
||||||
contents,
|
|
||||||
int(curr_dir) * "=",
|
|
||||||
root_dir,
|
|
||||||
ranc_dir
|
|
||||||
)
|
|
||||||
name_dir = root_dir
|
|
||||||
prev_dir = curr_dir
|
|
||||||
|
|
||||||
if prev_dir != curr_dir:
|
|
||||||
sanc_dir = uri_dir.rsplit("/")[int(curr_dir - 1)].replace(" ", "_")
|
|
||||||
index_l = '%s\n%s <a href="#%s">%s</a>'%(
|
|
||||||
index_l,
|
|
||||||
int(curr_dir) * "=",
|
|
||||||
sanc_dir,
|
|
||||||
uri_dir.rsplit("/")[int(curr_dir - 1)]
|
|
||||||
)
|
|
||||||
contents = '%s\n%s [%s] <a id="%s"></a>'%(
|
|
||||||
contents,
|
|
||||||
int(curr_dir) * "=",
|
|
||||||
uri_dir.rsplit("/")[int(curr_dir - 1)],
|
|
||||||
sanc_dir
|
|
||||||
)
|
|
||||||
prev_dir = curr_dir
|
|
||||||
|
|
||||||
contents = "%s\n%s _%s"%(
|
|
||||||
contents,
|
|
||||||
int(curr_dir + 1) * '=',
|
|
||||||
db.title
|
|
||||||
)
|
|
||||||
|
|
||||||
# Ending markers
|
|
||||||
index_l = "%s\n-)"%index_l
|
|
||||||
contents = "%s\n-)"%contents
|
|
||||||
|
|
||||||
# Fill new sitemap.tyto and create
|
|
||||||
sitemap_tyto = \
|
|
||||||
sitemap_tyto%(
|
|
||||||
nbr_files,
|
|
||||||
links,
|
|
||||||
index_l,
|
|
||||||
contents
|
|
||||||
)
|
|
||||||
sitemap_file = "%ssitemap.tyto"%dom.articles_d
|
|
||||||
tyto.set_file(sitemap_file, "New", sitemap_tyto)
|
|
||||||
|
|
||||||
# Check and wip
|
|
||||||
print()
|
|
||||||
www = subprocess.run(
|
|
||||||
[
|
|
||||||
'/usr/bin/tyto',
|
|
||||||
'force-wip',
|
|
||||||
'sitemap.tyto'
|
|
||||||
],
|
|
||||||
)
|
|
|
@ -1,206 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Tyto - Littérateur
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License
|
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# XMPP: echolib (im@echolib.re)
|
|
||||||
#
|
|
||||||
# Description: Load article's database and check validity
|
|
||||||
# File: /var/lib/tyto/program/db.py
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#-------------------------
|
|
||||||
# Funny Stats Project
|
|
||||||
#-------------------------
|
|
||||||
# file lines : 206
|
|
||||||
# file comments : 37
|
|
||||||
# file functions: 1
|
|
||||||
# file program : 152
|
|
||||||
#--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import args, logs, dom, form, tyto, check, publish
|
|
||||||
|
|
||||||
remove = exists = post = corrupt = file_wip = file_www = False
|
|
||||||
chk_again = chk_updated = False
|
|
||||||
wip_again = wip_added = wip_updated = False
|
|
||||||
www_again = www_added = www_updated = False
|
|
||||||
|
|
||||||
if dom.hole:
|
|
||||||
logs.out("13", '', True)
|
|
||||||
|
|
||||||
|
|
||||||
# target needs db (file).
|
|
||||||
# action like show, wip, edit-db
|
|
||||||
# not domain, all, again...
|
|
||||||
if args.target \
|
|
||||||
and args.action in args.pass_db \
|
|
||||||
and not args.target in args.pass_targets:
|
|
||||||
|
|
||||||
# Domain must be valid
|
|
||||||
if not dom.exists: logs.out("10", '', True)
|
|
||||||
|
|
||||||
uri_file = '%s%s'%(dom.articles_d, args.target)
|
|
||||||
uri_id = tyto.get_filesum(uri_file, False)
|
|
||||||
|
|
||||||
# Set DB file
|
|
||||||
config = '%s%s.config'%(dom.articles_db_d, uri_id)
|
|
||||||
if tyto.exists(config):
|
|
||||||
exists = True
|
|
||||||
try:
|
|
||||||
exec(open(config).read())
|
|
||||||
except:
|
|
||||||
exists = False
|
|
||||||
else:
|
|
||||||
exists = False
|
|
||||||
|
|
||||||
# Article file exists
|
|
||||||
if tyto.exists(uri_file):
|
|
||||||
post = True
|
|
||||||
hash_post = tyto.get_filesum(uri_file, True)
|
|
||||||
else:
|
|
||||||
remove = True
|
|
||||||
|
|
||||||
# Check if database config is valid (contains values)
|
|
||||||
if exists:
|
|
||||||
values = \
|
|
||||||
(
|
|
||||||
'post_id',
|
|
||||||
'post_src',
|
|
||||||
'post_wip',
|
|
||||||
'static_wip',
|
|
||||||
'post_www',
|
|
||||||
'static_www',
|
|
||||||
'direc_src',
|
|
||||||
'short_src',
|
|
||||||
'short_srv',
|
|
||||||
'sub_uri',
|
|
||||||
'http_wip',
|
|
||||||
'http_www',
|
|
||||||
'date_chk',
|
|
||||||
'hash_chk',
|
|
||||||
'date_wip',
|
|
||||||
'hash_wip',
|
|
||||||
'date_www',
|
|
||||||
'hash_www',
|
|
||||||
'title',
|
|
||||||
'about',
|
|
||||||
'author',
|
|
||||||
'meta_tags',
|
|
||||||
'date',
|
|
||||||
'snpic',
|
|
||||||
'sitemap',
|
|
||||||
'uris',
|
|
||||||
'uniq_anchors',
|
|
||||||
'uniq_abbrs',
|
|
||||||
'uniq_links',
|
|
||||||
'uniq_images',
|
|
||||||
'uniq_files',
|
|
||||||
'uniq_raws',
|
|
||||||
'comments',
|
|
||||||
'tags',
|
|
||||||
'words',
|
|
||||||
'titles',
|
|
||||||
'paragraphs',
|
|
||||||
'links',
|
|
||||||
'images',
|
|
||||||
'anchors',
|
|
||||||
'abbrs',
|
|
||||||
'strongs',
|
|
||||||
'bolds',
|
|
||||||
'emphasis',
|
|
||||||
'italics',
|
|
||||||
'dels',
|
|
||||||
'underlines',
|
|
||||||
'cites',
|
|
||||||
'customs',
|
|
||||||
'icodes',
|
|
||||||
'bcodes',
|
|
||||||
'quotes',
|
|
||||||
'lists',
|
|
||||||
'files',
|
|
||||||
'raws',
|
|
||||||
'codes',
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set exist for wip and www files
|
|
||||||
for value in values:
|
|
||||||
try:
|
|
||||||
eval(str(value))
|
|
||||||
except:
|
|
||||||
remove = True
|
|
||||||
corrupt = True
|
|
||||||
break
|
|
||||||
|
|
||||||
# Remove DB if unused source article or corrupted DB
|
|
||||||
if remove and exists:
|
|
||||||
os.remove(config)
|
|
||||||
exists = False
|
|
||||||
logs.out("23", config, False)
|
|
||||||
|
|
||||||
old_chk = old_wip = old_www = False
|
|
||||||
no_chk = no_wip = no_www = False
|
|
||||||
sync_srvs = False
|
|
||||||
|
|
||||||
# Set Statuses for chk, wip, www
|
|
||||||
if exists:
|
|
||||||
# File exists on servers
|
|
||||||
if tyto.exists(post_wip): file_wip = True
|
|
||||||
if tyto.exists(post_www): file_www = True
|
|
||||||
|
|
||||||
# Statuses not set in Db
|
|
||||||
if not hash_chk: no_chk = True
|
|
||||||
if not hash_wip: no_wip = True
|
|
||||||
if not hash_www: no_www = True
|
|
||||||
|
|
||||||
# Source article has changed
|
|
||||||
if hash_post != hash_chk: old_chk = chk_updated = True
|
|
||||||
if hash_chk: chk_again = True
|
|
||||||
|
|
||||||
# WIP article is old
|
|
||||||
if not old_chk:
|
|
||||||
if hash_wip and hash_chk != hash_wip: old_wip = wip_updated = True
|
|
||||||
if no_wip: wip_added = True
|
|
||||||
if hash_wip: wip_again = True
|
|
||||||
if not file_wip:
|
|
||||||
old_wip = wip_updated = True
|
|
||||||
wip_added = True
|
|
||||||
wip_again = True
|
|
||||||
|
|
||||||
# WWW article is old
|
|
||||||
if not old_wip:
|
|
||||||
if hash_www and hash_www != hash_wip: old_www = www_updated = True
|
|
||||||
if hash_www: www_again = True
|
|
||||||
if no_www: www_added = True
|
|
||||||
if not file_www:
|
|
||||||
old_www = www_updated = True
|
|
||||||
www_added = True
|
|
||||||
www_again = True
|
|
||||||
|
|
||||||
# Article is updated on both servers
|
|
||||||
if hash_chk == hash_wip == hash_www: sync_srvs = True
|
|
||||||
|
|
||||||
|
|
||||||
#=========================#
|
|
||||||
# Show title and uri file #
|
|
||||||
#-------------------------#
|
|
||||||
def show_title():
|
|
||||||
try:
|
|
||||||
print(' ├ "%s" > %s'%(title, uri_file))
|
|
||||||
except:
|
|
||||||
return
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Tyto - Littérateur
|
||||||
|
|
||||||
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# XMPP: echolib (im@echolib.re)
|
||||||
|
#
|
||||||
|
# Description: Add more logs when debug is set in command line
|
||||||
|
# File: /var/lib/tyto/program/debug.py
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-------------------------
|
||||||
|
# Funny Stats Project
|
||||||
|
#-------------------------
|
||||||
|
# file lines :
|
||||||
|
# file comments :
|
||||||
|
# file functions:
|
||||||
|
# file program :
|
||||||
|
#--------------------------
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import langs, args
|
||||||
|
|
||||||
|
|
||||||
|
#===================================#
|
||||||
|
# Show logs if "show" is True #
|
||||||
|
# -D argument for specific ones #
|
||||||
|
# color is for "*" in message #
|
||||||
|
# - 3 colors levels: #
|
||||||
|
# - - 0 = Green #
|
||||||
|
# - - 1 = Yellow #
|
||||||
|
# - - 2 = Red #
|
||||||
|
# stop to sys exit with nbr if True #
|
||||||
|
#-----------------------------------#
|
||||||
|
def out(nbr, var, val, show, color, stop):
|
||||||
|
args.get_options()
|
||||||
|
if not show and not args.dlogs: return # Show Very less logs
|
||||||
|
if args.erron and color == 0: return # Show only warn and error logs
|
||||||
|
|
||||||
|
# COlors
|
||||||
|
CS = '\033[0;0m' # Unset
|
||||||
|
CL = '\033[0;2m' # Gray
|
||||||
|
CB = '\033[1;34m' # Blue
|
||||||
|
CC = '\033[1;36m' # Cyan
|
||||||
|
CR = '\033[1;31m' # Red
|
||||||
|
CG = '\033[1;32m' # Green
|
||||||
|
CY = '\033[1;33m' # Yellow
|
||||||
|
CP = '\033[1;35m' # Pink
|
||||||
|
|
||||||
|
# Color of "*"
|
||||||
|
SC = CL # Default gray
|
||||||
|
if color == 0: SC = CG
|
||||||
|
elif color == 1: SC = CY
|
||||||
|
elif color == 2: SC = CR
|
||||||
|
|
||||||
|
# Messages for logs
|
||||||
|
messages = \
|
||||||
|
{
|
||||||
|
# ERRORS (1-100)
|
||||||
|
1 : langs.logs.err_arg,
|
||||||
|
2 : langs.logs.err_hole,
|
||||||
|
3 : langs.logs.err_dir,
|
||||||
|
4 : langs.logs.err_cd,
|
||||||
|
5 : langs.logs.err_no_file,
|
||||||
|
6 : langs.logs.err_no_dir,
|
||||||
|
7 : langs.logs.err_cr_file,
|
||||||
|
8 : langs.logs.err_lang,
|
||||||
|
50 : langs.logs.err_date,
|
||||||
|
# WARNINGS (100-200)
|
||||||
|
100 : langs.logs.warn_no_dom,
|
||||||
|
101 : langs.logs.domain_created,
|
||||||
|
102 : langs.logs.reset_dom,
|
||||||
|
103 : langs.logs.website_lang,
|
||||||
|
104 : langs.logs.domains_no,
|
||||||
|
# Great (200-255)
|
||||||
|
200 : langs.logs.load_file,
|
||||||
|
201 : langs.logs.lang_logs_sys,
|
||||||
|
202 : langs.logs.domain_found,
|
||||||
|
203 : langs.logs.created_dir,
|
||||||
|
204 : langs.logs.domain_updated,
|
||||||
|
205 : langs.logs.domain_new,
|
||||||
|
206 : langs.logs.created_file,
|
||||||
|
207 : langs.logs.updated_file,
|
||||||
|
208 : langs.logs.website_lang,
|
||||||
|
255 : langs.logs.later,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Print, acoording to parameters
|
||||||
|
print("%s*%s %s%s%s > %s%s%s < %s%s%s"%(
|
||||||
|
SC, CS,
|
||||||
|
CL, messages[nbr], CS,
|
||||||
|
CB, var, CS,
|
||||||
|
CC, val, CS
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Exit if stop = True
|
||||||
|
if stop:
|
||||||
|
if nbr >= 200:
|
||||||
|
nbr = 0
|
||||||
|
sys.exit(nbr)
|
||||||
|
|
|
@ -1,318 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Tyto - Littérateur
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License
|
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# XMPP: echolib (im@echolib.re)
|
|
||||||
#
|
|
||||||
# Description: Load domain database and check validity
|
|
||||||
# File: /var/lib/tyto/program/dom.py
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#-------------------------
|
|
||||||
# Funny Stats Project
|
|
||||||
#-------------------------
|
|
||||||
# file lines : 318
|
|
||||||
# file comments : 31
|
|
||||||
# file functions: 1
|
|
||||||
# file program : 277
|
|
||||||
#--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
import os, sys, importlib, langs
|
|
||||||
import args
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
ready
|
|
||||||
|
|
||||||
except:
|
|
||||||
|
|
||||||
lib = 'tyto_domain'
|
|
||||||
exists = incomplete = active = ready = shortname = corrupt = False
|
|
||||||
local_user = articles_db_d = False
|
|
||||||
hole = False
|
|
||||||
|
|
||||||
# Set current directory
|
|
||||||
try:
|
|
||||||
user_dir
|
|
||||||
except:
|
|
||||||
try:
|
|
||||||
user_dir = os.getcwd() + "/"
|
|
||||||
except:
|
|
||||||
hole = True
|
|
||||||
|
|
||||||
# Set current user name
|
|
||||||
try:
|
|
||||||
user
|
|
||||||
except:
|
|
||||||
try:
|
|
||||||
user = os.environ.get('USER')
|
|
||||||
except:
|
|
||||||
user = ''
|
|
||||||
|
|
||||||
|
|
||||||
# Settings for domain, check if db is not corrupted
|
|
||||||
dom_values = \
|
|
||||||
(
|
|
||||||
'directory',
|
|
||||||
'database',
|
|
||||||
'local_user',
|
|
||||||
'lang_sys',
|
|
||||||
'lang_logs',
|
|
||||||
'articles_db_d',
|
|
||||||
'articles_d',
|
|
||||||
'files_d',
|
|
||||||
'images_d',
|
|
||||||
'modules_d',
|
|
||||||
'navbar_f',
|
|
||||||
'sidebar_f',
|
|
||||||
'metas_f',
|
|
||||||
'footer_f',
|
|
||||||
'shortname',
|
|
||||||
'www_url',
|
|
||||||
'wip_url',
|
|
||||||
'srv_root',
|
|
||||||
'srv_domain',
|
|
||||||
'srv_wip',
|
|
||||||
'srv_wip_tpl_d',
|
|
||||||
'srv_wip_images_d',
|
|
||||||
'srv_wip_files_d',
|
|
||||||
'srv_www',
|
|
||||||
'srv_www_tpl_d',
|
|
||||||
'srv_www_images_d',
|
|
||||||
'srv_www_files_d',
|
|
||||||
'wip_favicon_f',
|
|
||||||
'wip_css_f',
|
|
||||||
'wip_logo_f',
|
|
||||||
'wip_navbar_f',
|
|
||||||
'wip_sidebar_f',
|
|
||||||
'wip_metas_f',
|
|
||||||
'wip_footer_f',
|
|
||||||
'wip_stats_f',
|
|
||||||
'www_navbar_f',
|
|
||||||
'www_sidebar_f',
|
|
||||||
'www_metas_f',
|
|
||||||
'www_footer_f',
|
|
||||||
'www_stats_f',
|
|
||||||
'www_logo_f',
|
|
||||||
'www_css_f',
|
|
||||||
'www_rss_f',
|
|
||||||
'www_favicon_f',
|
|
||||||
'favicon',
|
|
||||||
'logo',
|
|
||||||
'styles',
|
|
||||||
'rss',
|
|
||||||
'rss_items',
|
|
||||||
'title',
|
|
||||||
'date',
|
|
||||||
'about',
|
|
||||||
'lang_site',
|
|
||||||
'mail',
|
|
||||||
'tags',
|
|
||||||
'license',
|
|
||||||
'license_url',
|
|
||||||
'legal_url',
|
|
||||||
'terms_url',
|
|
||||||
'css',
|
|
||||||
'sep',
|
|
||||||
'article_code',
|
|
||||||
'relme',
|
|
||||||
'sidebar_title',
|
|
||||||
'sidebar_items',
|
|
||||||
'activated'
|
|
||||||
)
|
|
||||||
|
|
||||||
create_files = \
|
|
||||||
(
|
|
||||||
'navbar_f',
|
|
||||||
'sidebar_f',
|
|
||||||
'metas_f',
|
|
||||||
'footer_f',
|
|
||||||
)
|
|
||||||
|
|
||||||
wip_html_mods = ()
|
|
||||||
err_val = (()) # Make a list from values error
|
|
||||||
|
|
||||||
if not hole:
|
|
||||||
home_dir = os.path.expanduser('~')
|
|
||||||
|
|
||||||
# Set configuration domain directory
|
|
||||||
root_dir = user_dir
|
|
||||||
if '/articles' in user_dir:
|
|
||||||
root_dir = user_dir.rsplit('/articles')[0] + "/"
|
|
||||||
|
|
||||||
# Set configuration domain file
|
|
||||||
config = '%styto_domain.py'%root_dir
|
|
||||||
shortname = config
|
|
||||||
|
|
||||||
# Set exists if configuration file
|
|
||||||
if os.path.exists(config):
|
|
||||||
exists = True
|
|
||||||
try:
|
|
||||||
exec(open(config).read())
|
|
||||||
try:
|
|
||||||
os.path.exists(articles_d)
|
|
||||||
if '/articles' in user_dir:
|
|
||||||
user_uri_dir = user_dir.rsplit(articles_d)[1]
|
|
||||||
else:
|
|
||||||
user_uri_dir = ''
|
|
||||||
os.chdir(articles_d)
|
|
||||||
except: corrupt = True
|
|
||||||
except:
|
|
||||||
corrupt = True
|
|
||||||
|
|
||||||
if not args.target in args.pass_targets:
|
|
||||||
if args.target.startswith("articles/"):
|
|
||||||
args.target = args.target.rsplit("articles/")[1]
|
|
||||||
args.target = user_uri_dir + args.target
|
|
||||||
|
|
||||||
# For logs: show uri if not shortname known
|
|
||||||
try: shortname
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
try: active = activated
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
# Check set values configuration
|
|
||||||
if not corrupt:
|
|
||||||
for value in dom_values:
|
|
||||||
try:
|
|
||||||
eval(str(value))
|
|
||||||
value_set = True
|
|
||||||
except:
|
|
||||||
err_val = err_val + ((value),)
|
|
||||||
value_set = False
|
|
||||||
incomplete = True
|
|
||||||
active = False
|
|
||||||
|
|
||||||
|
|
||||||
#==============================================#
|
|
||||||
# When an active and complete domain is needed #
|
|
||||||
#----------------------------------------------#
|
|
||||||
if exists and not incomplete and not corrupt:
|
|
||||||
if active:
|
|
||||||
ready = True
|
|
||||||
|
|
||||||
wip_html_mods = \
|
|
||||||
(
|
|
||||||
eval(str('wip_navbar_f')),
|
|
||||||
eval(str('wip_sidebar_f')),
|
|
||||||
eval(str('wip_metas_f')),
|
|
||||||
eval(str('wip_footer_f'))
|
|
||||||
)
|
|
||||||
www_html_mods = \
|
|
||||||
(
|
|
||||||
eval(str('www_navbar_f')),
|
|
||||||
eval(str('www_sidebar_f')),
|
|
||||||
eval(str('www_metas_f')),
|
|
||||||
eval(str('www_footer_f'))
|
|
||||||
)
|
|
||||||
metas = \
|
|
||||||
(
|
|
||||||
eval(str('metas_f')),
|
|
||||||
eval(str('wip_metas_f')),
|
|
||||||
eval(str('www_metas_f'))
|
|
||||||
)
|
|
||||||
navbars = \
|
|
||||||
(
|
|
||||||
eval(str('navbar_f')),
|
|
||||||
eval(str('wip_navbar_f')),
|
|
||||||
eval(str('www_navbar_f'))
|
|
||||||
)
|
|
||||||
sidebars = \
|
|
||||||
(
|
|
||||||
eval(str('sidebar_f')),
|
|
||||||
eval(str('wip_sidebar_f')),
|
|
||||||
eval(str('www_sidebar_f'))
|
|
||||||
)
|
|
||||||
footers = \
|
|
||||||
(
|
|
||||||
eval(str('footer_f')),
|
|
||||||
eval(str('wip_footer_f')),
|
|
||||||
eval(str('www_footer_f')),
|
|
||||||
)
|
|
||||||
|
|
||||||
templates = \
|
|
||||||
(
|
|
||||||
eval(str('wip_logo_f')),
|
|
||||||
eval(str('wip_favicon_f')),
|
|
||||||
eval(str('wip_css_f')),
|
|
||||||
eval(str('wip_navbar_f')),
|
|
||||||
eval(str('wip_sidebar_f')),
|
|
||||||
eval(str('wip_metas_f')),
|
|
||||||
eval(str('wip_footer_f')),
|
|
||||||
eval(str('wip_stats_f')),
|
|
||||||
eval(str('www_favicon_f')),
|
|
||||||
eval(str('www_logo_f')),
|
|
||||||
eval(str('www_css_f')),
|
|
||||||
eval(str('www_navbar_f')),
|
|
||||||
eval(str('www_sidebar_f')),
|
|
||||||
eval(str('www_metas_f')),
|
|
||||||
eval(str('www_footer_f')),
|
|
||||||
eval(str('www_stats_f')),
|
|
||||||
eval(str('www_rss_f')),
|
|
||||||
)
|
|
||||||
|
|
||||||
statistics = \
|
|
||||||
(
|
|
||||||
eval(str('wip_stats_f')),
|
|
||||||
eval(str('www_stats_f')),
|
|
||||||
)
|
|
||||||
|
|
||||||
modules = \
|
|
||||||
{
|
|
||||||
"metas" : metas,
|
|
||||||
"navbar" : navbars,
|
|
||||||
"sidebar" : sidebars,
|
|
||||||
"footer" : footers,
|
|
||||||
"template": templates,
|
|
||||||
"stats" : statistics,
|
|
||||||
}
|
|
||||||
|
|
||||||
templates_files_wip = \
|
|
||||||
(
|
|
||||||
eval(str('wip_favicon_f')),
|
|
||||||
eval(str('wip_logo_f')),
|
|
||||||
eval(str('wip_css_f')),
|
|
||||||
eval(str('wip_navbar_f')),
|
|
||||||
eval(str('wip_sidebar_f')),
|
|
||||||
eval(str('wip_metas_f')),
|
|
||||||
eval(str('wip_footer_f')),
|
|
||||||
eval(str('wip_stats_f')),
|
|
||||||
)
|
|
||||||
|
|
||||||
templates_files_www = \
|
|
||||||
(
|
|
||||||
eval(str('www_favicon_f')),
|
|
||||||
eval(str('www_logo_f')),
|
|
||||||
eval(str('www_css_f')),
|
|
||||||
eval(str('www_navbar_f')),
|
|
||||||
eval(str('www_sidebar_f')),
|
|
||||||
eval(str('www_metas_f')),
|
|
||||||
eval(str('www_footer_f')),
|
|
||||||
eval(str('www_stats_f')),
|
|
||||||
eval(str('www_rss_f'))
|
|
||||||
)
|
|
||||||
|
|
||||||
#====================================#
|
|
||||||
# Check if domain is ready and ready #
|
|
||||||
#------------------------------------#
|
|
||||||
def valid():
|
|
||||||
if incomplete: sys.exit(41)
|
|
||||||
elif not active: sys.exit(42)
|
|
||||||
elif not ready: sys.exit(41)
|
|
|
@ -0,0 +1,376 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Tyto - Littérateur
|
||||||
|
|
||||||
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# XMPP: echolib (im@echolib.re)
|
||||||
|
#
|
||||||
|
# Description: Manage configuration domain(s)
|
||||||
|
# File: /var/lib/tyto/program/domain.py
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-------------------------
|
||||||
|
# Funny Stats Project
|
||||||
|
#-------------------------
|
||||||
|
# file lines :
|
||||||
|
# file comments :
|
||||||
|
# file functions:
|
||||||
|
# file program :
|
||||||
|
#--------------------------
|
||||||
|
|
||||||
|
import os, sys, configparser
|
||||||
|
import debug, tyto, tools, forms, langs
|
||||||
|
|
||||||
|
|
||||||
|
#=========================================================#
|
||||||
|
# Exit if directory name is compatible with a domain name #
|
||||||
|
#---------------------------------------------------------#
|
||||||
|
def compatible_name():
|
||||||
|
if len(conf_name.rsplit(".")) <= 1:
|
||||||
|
debug.out(3, "abc.tld", conf_name, True, 2, True)
|
||||||
|
|
||||||
|
|
||||||
|
#================================#
|
||||||
|
# Load Domain Configuration file #
|
||||||
|
# As needed, exit if not exists #
|
||||||
|
#--------------------------------#
|
||||||
|
def dcf_load():
|
||||||
|
global dcf
|
||||||
|
|
||||||
|
dcf = False
|
||||||
|
if not dcf_exists():
|
||||||
|
debug.out(100, conf_name, dcf_uri, True, 1, True)
|
||||||
|
|
||||||
|
dcf = configparser.ConfigParser()
|
||||||
|
dcf.read(dcf_uri)
|
||||||
|
|
||||||
|
|
||||||
|
#=====================================#
|
||||||
|
# Load User Domain Configuration file #
|
||||||
|
# As needed, exit if not exists #
|
||||||
|
#-------------------------------------#
|
||||||
|
def ult_dcf_load():
|
||||||
|
global ult_dcf
|
||||||
|
|
||||||
|
ult_dcf = False
|
||||||
|
if not os.path.exists(ult_dcf_uri):
|
||||||
|
debug.out(100, conf_name, ult_dcf_uri, True, 1, True)
|
||||||
|
|
||||||
|
ult_dcf = configparser.ConfigParser()
|
||||||
|
ult_dcf.read(ult_dcf_uri)
|
||||||
|
|
||||||
|
|
||||||
|
#===================================#
|
||||||
|
# Load User local Domains List File #
|
||||||
|
#-----------------------------------#
|
||||||
|
def ult_dlf_load():
|
||||||
|
global ult_dlf
|
||||||
|
|
||||||
|
ult_dlf = False
|
||||||
|
ult_dlf = configparser.ConfigParser()
|
||||||
|
ult_dlf.read(ult_dlf_uri)
|
||||||
|
|
||||||
|
|
||||||
|
#===========================================#
|
||||||
|
# Check if Domain COnfiguration file exists #
|
||||||
|
# Show status message only once #
|
||||||
|
# return True or False
|
||||||
|
#-------------------------------------------#
|
||||||
|
def dcf_exists():
|
||||||
|
global shown_ok, shown_no
|
||||||
|
|
||||||
|
if os.path.exists(dcf_uri):
|
||||||
|
try: shown_ok
|
||||||
|
except: debug.out(202, conf_name, dcf_uri, True, 0, False)
|
||||||
|
shown_ok = True
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
try: shown_no
|
||||||
|
except: debug.out(100, "False", dcf_uri, True, 1, False)
|
||||||
|
shown_no = True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
#=============================================#
|
||||||
|
# Ensure domain is valid and ready to be used #
|
||||||
|
#---------------------------------------------#
|
||||||
|
def valid_conf():
|
||||||
|
dcf_load()
|
||||||
|
try:
|
||||||
|
dcf_name = dcf.get("DOMAIN", "name")
|
||||||
|
except:
|
||||||
|
debug.out(100, conf_name, dcf_uri, True, 1, True)
|
||||||
|
|
||||||
|
# Check some values in ult_dcf
|
||||||
|
ult_dcf_load()
|
||||||
|
try:
|
||||||
|
ult_dcf_name = ult_dcf.get("DOMAIN", "name")
|
||||||
|
ult_dcf_hash = ult_dcf.get("DOMAIN", "hash")
|
||||||
|
ult_dcf_conf = ult_dcf.get("DOMAIN", "conf")
|
||||||
|
ult_dcf_root = ult_dcf.get("DOMAIN", "root")
|
||||||
|
except:
|
||||||
|
debug.out(100, conf_name, ult_dcf_uri, True, 1, True)
|
||||||
|
|
||||||
|
# Compare values (exit if mismatch)
|
||||||
|
if ult_dcf_name != conf_name or \
|
||||||
|
ult_dcf_conf != dcf_uri or \
|
||||||
|
dcf_name != ult_dcf_name:
|
||||||
|
debug.out(100, conf_name, "?", True, 1, True)
|
||||||
|
|
||||||
|
# Check if dcf need to be updated
|
||||||
|
now_dcf_hash = tools.get_filesum(dcf_uri, True)
|
||||||
|
if now_dcf_hash != ult_dcf_hash:
|
||||||
|
dcf_update_values("")
|
||||||
|
|
||||||
|
|
||||||
|
#=========================================#
|
||||||
|
# Guess and return wip_url from conf_name #
|
||||||
|
#-----------------------------------------#
|
||||||
|
def create_wip_url():
|
||||||
|
wip_url = "https://www-wip.%s/"
|
||||||
|
len_cn = conf_name.count(".")
|
||||||
|
|
||||||
|
# Domain name Format: a.b
|
||||||
|
if len_cn == 1:
|
||||||
|
return wip_url%conf_name
|
||||||
|
|
||||||
|
# Domain name format: (at least) a.b.c
|
||||||
|
len_cn = len(conf_name.rsplit(".")[0]) + 1
|
||||||
|
tld = conf_name[len_cn:]
|
||||||
|
return wip_url%tld
|
||||||
|
|
||||||
|
|
||||||
|
#==========================================#
|
||||||
|
# Ask User to create new domain #
|
||||||
|
# Create NEW #:
|
||||||
|
# - default Domain Configuration file #
|
||||||
|
# - default User domain configuration file #
|
||||||
|
# If not User domains list file, create it #
|
||||||
|
#------------------------------------------#
|
||||||
|
def dcf_create():
|
||||||
|
compatible_name()
|
||||||
|
|
||||||
|
# This fonction is only called with "new domain" argument
|
||||||
|
# If a conf already exists, show important RESET log
|
||||||
|
if dcf_exists():
|
||||||
|
debug.out(102, "!?", dcf_uri, True, 1, False)
|
||||||
|
|
||||||
|
# Ask User to create new domain. Will exit if not ok.
|
||||||
|
forms.ask_domain_shortname(conf_name)
|
||||||
|
|
||||||
|
# Create default files
|
||||||
|
tools.create_file(dcf_uri, tyto.ini_domain)
|
||||||
|
tools.create_dirs(ult_dir)
|
||||||
|
tools.create_file(ult_dcf_uri, tyto.ini_domain_user)
|
||||||
|
|
||||||
|
# User Domains list file
|
||||||
|
if not os.path.exists(ult_dlf_uri):
|
||||||
|
tools.create_file(ult_dlf_uri, tyto.ini_domains_list)
|
||||||
|
|
||||||
|
# Ask user for domain settings
|
||||||
|
forms.ask_domain_title()
|
||||||
|
forms.ask_domain_date()
|
||||||
|
forms.ask_domain_about()
|
||||||
|
forms.ask_domain_mail()
|
||||||
|
forms.ask_domain_tags()
|
||||||
|
|
||||||
|
# Set default lang, from config file or system lang
|
||||||
|
forms.ask_domain_lang()
|
||||||
|
|
||||||
|
# Set server directory
|
||||||
|
forms.ask_domain_server()
|
||||||
|
|
||||||
|
|
||||||
|
#===========================================#
|
||||||
|
# Set or Update domain configuration values #
|
||||||
|
#-------------------------------------------#
|
||||||
|
def dcf_update_values(srv):
|
||||||
|
# Prepare Domain Configuration File keys values
|
||||||
|
#-----------------------------------------------
|
||||||
|
dcf_load()
|
||||||
|
|
||||||
|
# Test server directory, and exit if not exists
|
||||||
|
if not srv: srv = dcf.get("SERVER", "root") # Set from db if unknown
|
||||||
|
if srv: tools.dir_exists(srv, True)
|
||||||
|
|
||||||
|
# Test registred website lang
|
||||||
|
# change to default lang sys, or "en" if no translation file
|
||||||
|
langs.load_website_lang()
|
||||||
|
|
||||||
|
srv_dom = os.path.join(srv, conf_name + "/")
|
||||||
|
srv_wip = os.path.join(srv_dom, "wip/")
|
||||||
|
srv_www = os.path.join(srv_dom, "www/")
|
||||||
|
|
||||||
|
favicon = dcf.get("TEMPLATE_FILENAMES", "favicon")
|
||||||
|
logo = dcf.get("TEMPLATE_FILENAMES", "logo")
|
||||||
|
styles = dcf.get("TEMPLATE_FILENAMES", "styles")
|
||||||
|
rss = dcf.get("TEMPLATE_FILENAMES", "rss")
|
||||||
|
stats = dcf.get("TEMPLATE_FILENAMES", "stats")
|
||||||
|
|
||||||
|
www_url = dcf.get("WEBSITE", "www_url")
|
||||||
|
wip_url = dcf.get("WEBSITE", "wip_url")
|
||||||
|
|
||||||
|
sdb_title = dcf.get("WEBSITE_MODULES", "sidebar_title")
|
||||||
|
|
||||||
|
usr_mods = os.path.join(dcf_dir + "modules/")
|
||||||
|
usr_tpl = os.path.join(dcf_dir, "template/")
|
||||||
|
usr_favicon = os.path.join(usr_tpl, favicon)
|
||||||
|
usr_logo = os.path.join(usr_tpl, logo)
|
||||||
|
usr_styles = os.path.join(usr_tpl, styles)
|
||||||
|
|
||||||
|
wip_tpl = srv_wip + "template/"
|
||||||
|
wip_favicon = os.path.join(wip_tpl, favicon)
|
||||||
|
wip_logo = os.path.join(wip_tpl, logo)
|
||||||
|
wip_styles = os.path.join(wip_tpl, styles)
|
||||||
|
wip_rss = os.path.join(wip_tpl, rss)
|
||||||
|
wip_stats = os.path.join(wip_tpl, stats)
|
||||||
|
|
||||||
|
www_tpl = srv_www + "template/"
|
||||||
|
www_favicon = os.path.join(www_tpl, favicon)
|
||||||
|
www_logo = os.path.join(www_tpl, logo)
|
||||||
|
www_styles = os.path.join(www_tpl, styles)
|
||||||
|
www_rss = os.path.join(www_tpl, rss)
|
||||||
|
www_stats = os.path.join(www_tpl, stats)
|
||||||
|
|
||||||
|
|
||||||
|
# Update Domain Configuration File
|
||||||
|
#---------------------------------
|
||||||
|
dcf.set("DOMAIN", "name", conf_name)
|
||||||
|
dcf.set("TYTO", "domain_hash", tools.get_filesum(dcf_uri, False))
|
||||||
|
dcf.set("TYTO", "domain_conf", dcf_uri)
|
||||||
|
dcf.set("TYTO", "domain_user", ult_dcf_uri)
|
||||||
|
|
||||||
|
# USER
|
||||||
|
dcf.set("USER_DIRS", "root", dcf_dir)
|
||||||
|
dcf.set("USER_DIRS", "articles", dcf_dir + "articles/")
|
||||||
|
dcf.set("USER_DIRS", "images", dcf_dir + "images/")
|
||||||
|
dcf.set("USER_DIRS", "files", dcf_dir + "files/")
|
||||||
|
dcf.set("USER_DIRS", "modules", usr_mods)
|
||||||
|
dcf.set("USER_DIRS", "database", dcf_dir + ".db/")
|
||||||
|
dcf.set("USER_DIRS", "template", usr_tpl)
|
||||||
|
dcf.set("USER_MODULES_FILES", "metas", usr_mods + "tyto_metas.raw")
|
||||||
|
dcf.set("USER_MODULES_FILES", "header", usr_mods + "tyto_header.raw")
|
||||||
|
dcf.set("USER_MODULES_FILES", "navbar", usr_mods + "tyto_navbar.raw")
|
||||||
|
dcf.set("USER_MODULES_FILES", "sidebar", usr_mods + "tyto_sidebar.raw")
|
||||||
|
dcf.set("USER_MODULES_FILES", "footer", usr_mods + "tyto_footer.raw")
|
||||||
|
dcf.set("USER_TEMPLATE_FILES", "favicon", usr_favicon)
|
||||||
|
dcf.set("USER_TEMPLATE_FILES", "logo", usr_logo)
|
||||||
|
dcf.set("USER_TEMPLATE_FILES", "styles", usr_styles)
|
||||||
|
|
||||||
|
# WEBSITE
|
||||||
|
dcf.set("WEBSITE", "lang", langs.site_lang)
|
||||||
|
www_url or dcf.set("WEBSITE", "www_url", "https://%s/"%conf_name)
|
||||||
|
wip_url or dcf.set("WEBSITE", "wip_url", create_wip_url())
|
||||||
|
|
||||||
|
sdb_title or dcf.set("WEBSITE_MODULES", "sidebar_title", langs.site.sidebar_title)
|
||||||
|
|
||||||
|
# SERVER
|
||||||
|
dcf.set("SERVER", "root", srv)
|
||||||
|
dcf.set("SERVER", "domain", srv_dom)
|
||||||
|
|
||||||
|
# WIP
|
||||||
|
dcf.set("WIP_DIRS", "root", srv_wip)
|
||||||
|
dcf.set("WIP_DIRS", "images", srv_wip + "images/")
|
||||||
|
dcf.set("WIP_DIRS", "files", srv_wip + "files/")
|
||||||
|
dcf.set("WIP_DIRS", "template", wip_tpl)
|
||||||
|
dcf.set("WIP_FILES", "favicon", wip_favicon)
|
||||||
|
dcf.set("WIP_FILES", "logo", wip_logo)
|
||||||
|
dcf.set("WIP_FILES", "styles", wip_styles)
|
||||||
|
dcf.set("WIP_FILES", "rss", wip_rss)
|
||||||
|
dcf.set("WIP_FILES", "stats", wip_stats)
|
||||||
|
dcf.set("WIP_FILES", "metas", wip_tpl + "metas.html")
|
||||||
|
dcf.set("WIP_FILES", "header", wip_tpl + "header.html")
|
||||||
|
dcf.set("WIP_FILES", "navbar", wip_tpl + "navbar.html")
|
||||||
|
dcf.set("WIP_FILES", "sidebar", wip_tpl + "sidebar.html")
|
||||||
|
dcf.set("WIP_FILES", "footer", wip_tpl + "footer.html")
|
||||||
|
|
||||||
|
|
||||||
|
# WWW
|
||||||
|
dcf.set("WWW_DIRS", "root", srv_www)
|
||||||
|
dcf.set("WWW_DIRS", "images", srv_www + "images/")
|
||||||
|
dcf.set("WWW_DIRS", "files", srv_www + "files/")
|
||||||
|
dcf.set("WWW_DIRS", "template", www_tpl)
|
||||||
|
dcf.set("WWW_FILES", "favicon", www_favicon)
|
||||||
|
dcf.set("WWW_FILES", "logo", www_logo)
|
||||||
|
dcf.set("WWW_FILES", "styles", www_styles)
|
||||||
|
dcf.set("WWW_FILES", "rss", www_rss)
|
||||||
|
dcf.set("WWW_FILES", "stats", www_stats)
|
||||||
|
dcf.set("WWW_FILES", "metas", www_tpl + "metas.html")
|
||||||
|
dcf.set("WWW_FILES", "header", www_tpl + "header.html")
|
||||||
|
dcf.set("WWW_FILES", "navbar", www_tpl + "navbar.html")
|
||||||
|
dcf.set("WWW_FILES", "sidebar", www_tpl + "sidebar.html")
|
||||||
|
dcf.set("WWW_FILES", "footer", www_tpl + "footer.html")
|
||||||
|
|
||||||
|
with open(dcf_uri, "w") as f:
|
||||||
|
dcf.write(f)
|
||||||
|
|
||||||
|
# Update User local domain configuration file
|
||||||
|
#--------------------------------------------
|
||||||
|
ult_dcf_load()
|
||||||
|
ult_dcf.set("DOMAIN", "name", conf_name)
|
||||||
|
ult_dcf.set("DOMAIN", "hash", tools.get_filesum(dcf_uri, True))
|
||||||
|
ult_dcf.set("DOMAIN", "root", dcf_dir)
|
||||||
|
ult_dcf.set("DOMAIN", "conf", dcf_uri)
|
||||||
|
ult_dcf.set("SERVER", "root", srv)
|
||||||
|
|
||||||
|
with open(ult_dcf_uri, "w") as f:
|
||||||
|
ult_dcf.write(f)
|
||||||
|
|
||||||
|
# Update User local Domains List File
|
||||||
|
#------------------------------------
|
||||||
|
ult_dlf_load()
|
||||||
|
ult_dlf.set("DOMAINS", conf_name, dcf_dir)
|
||||||
|
|
||||||
|
with open(ult_dlf_uri, "w") as f:
|
||||||
|
ult_dlf.write(f)
|
||||||
|
|
||||||
|
debug.out(204, "True", dcf_uri, True, 0, False)
|
||||||
|
|
||||||
|
|
||||||
|
#======#=======================================================================
|
||||||
|
# MAIN #
|
||||||
|
#------#
|
||||||
|
#===================================#
|
||||||
|
# Check if current directory exists #
|
||||||
|
# Exit Tyto if in black hole... #
|
||||||
|
#-----------------------------------#
|
||||||
|
try:
|
||||||
|
user_dir = os.getcwd() + "/"
|
||||||
|
home_dir = os.path.expanduser('~')
|
||||||
|
except:
|
||||||
|
debug.out(2, "PWD", "?", True, 2, True)
|
||||||
|
|
||||||
|
|
||||||
|
#==========================================#
|
||||||
|
# utl: $USER/.local/Tyto #
|
||||||
|
# dcf: Domain Configuration File #
|
||||||
|
#------------------------------------------#
|
||||||
|
# Domain Configuration directory
|
||||||
|
dcf_dir = user_dir.rsplit("articles/")[0]
|
||||||
|
|
||||||
|
# Domain name from current basename directory
|
||||||
|
# Exit if not format at least "abc.tld"
|
||||||
|
conf_name = os.path.basename(os.path.dirname(dcf_dir))
|
||||||
|
|
||||||
|
dcf_name = "tyto_domain.ini"
|
||||||
|
dcf_uri = os.path.join(dcf_dir, dcf_name)
|
||||||
|
dcf_id = tools.get_filesum(dcf_uri, False) # ID from URI
|
||||||
|
|
||||||
|
# Tyto directory in home local user files
|
||||||
|
ult_dir = os.path.join(home_dir, ".local/Tyto/")
|
||||||
|
ult_dlf_uri = os.path.join(ult_dir, "domains.ini") # Domains list file
|
||||||
|
ult_dcf_uri = os.path.join(ult_dir, dcf_id + ".ini")
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,243 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Tyto - Littérateur
|
||||||
|
|
||||||
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# XMPP: echolib (im@echolib.re)
|
||||||
|
#
|
||||||
|
# Description: Forms (edit, create domain, questions...)
|
||||||
|
# File: /var/lib/tyto/program/form.py
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-------------------------
|
||||||
|
# Funny Stats Project
|
||||||
|
#-------------------------
|
||||||
|
# file lines :
|
||||||
|
# file comments :
|
||||||
|
# file functions:
|
||||||
|
# file program :
|
||||||
|
#--------------------------
|
||||||
|
|
||||||
|
import os, re, configparser
|
||||||
|
import debug, domain, langs, tools
|
||||||
|
|
||||||
|
|
||||||
|
#====================#
|
||||||
|
# Exit Tyto with log #
|
||||||
|
# user interrupts... #
|
||||||
|
#--------------------#
|
||||||
|
def maybe_later(expected, answer):
|
||||||
|
debug.out(255, expected, answer, True, 0, True)
|
||||||
|
|
||||||
|
|
||||||
|
#=========================#
|
||||||
|
# When asking something #
|
||||||
|
# yes_only : True / False #
|
||||||
|
#-------------------------#
|
||||||
|
def ask(q, yes_only, default):
|
||||||
|
expected = ""
|
||||||
|
if yes_only:
|
||||||
|
expected = langs.logs.ok
|
||||||
|
|
||||||
|
try:
|
||||||
|
answer = input(q)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("")
|
||||||
|
maybe_later(expected, "?")
|
||||||
|
|
||||||
|
# return default answer if exists
|
||||||
|
if not answer:
|
||||||
|
if default:
|
||||||
|
return default
|
||||||
|
|
||||||
|
maybe_later(expected, "?")
|
||||||
|
|
||||||
|
# Answer is a Y/N process
|
||||||
|
if yes_only:
|
||||||
|
for ok in langs.logs.ok:
|
||||||
|
if answer.lower() == ok.lower():
|
||||||
|
return True
|
||||||
|
maybe_later(expected, answer)
|
||||||
|
|
||||||
|
return answer
|
||||||
|
|
||||||
|
|
||||||
|
#====================================#
|
||||||
|
# Shorter value to show in questions #
|
||||||
|
# return value[0:12]
|
||||||
|
#------------------------------------#
|
||||||
|
def shorter(value):
|
||||||
|
if len(value) > 12:
|
||||||
|
return '%s...'%(value[0:12])
|
||||||
|
|
||||||
|
# Or legacy
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
#=========================#
|
||||||
|
# Confirm domain name #
|
||||||
|
# from directory basename #
|
||||||
|
# ------------------------#
|
||||||
|
def ask_domain_shortname(config_name):
|
||||||
|
q = "> %s (%s)%s "%(langs.logs.configure_domain, config_name, langs.logs.q)
|
||||||
|
ask(q, True, False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#======================#
|
||||||
|
# Getting domain Title #
|
||||||
|
#----------------------#
|
||||||
|
def ask_domain_title():
|
||||||
|
domain.dcf_load()
|
||||||
|
title = domain.dcf.get("DOMAIN", "title")
|
||||||
|
|
||||||
|
q = "> %s (%s)%s "%(langs.logs.domain_title, shorter(title), langs.logs.q)
|
||||||
|
answer = ask(q, False, title)
|
||||||
|
if answer != title:
|
||||||
|
tools.update_ini_file(domain.dcf_uri, "DOMAIN", "title", answer)
|
||||||
|
|
||||||
|
|
||||||
|
#===========================#
|
||||||
|
# Get domain creation date #
|
||||||
|
# Check if date match regex #
|
||||||
|
#---------------------------#
|
||||||
|
def ask_domain_date():
|
||||||
|
domain.dcf_load()
|
||||||
|
date = domain.dcf.get("DOMAIN", "date")
|
||||||
|
example = date or "YYYY[-MM-DD]"
|
||||||
|
|
||||||
|
q = "> %s (%s)%s "%(langs.logs.domain_date, example, langs.logs.q)
|
||||||
|
answer = ask(q, False, date)
|
||||||
|
|
||||||
|
# Check date format (not valid date)
|
||||||
|
test = True
|
||||||
|
tuple_date = answer.rsplit("-")
|
||||||
|
tuple_len = len(tuple_date)
|
||||||
|
for i in range(tuple_len):
|
||||||
|
if i == 0:
|
||||||
|
if len(tuple_date[i]) != 4 or not tuple_date[i].isdigit():
|
||||||
|
test = False
|
||||||
|
break
|
||||||
|
elif len(tuple_date[i]) != 2 or not tuple_date[i].isdigit():
|
||||||
|
test = False
|
||||||
|
break
|
||||||
|
|
||||||
|
# Exit if not valid
|
||||||
|
if not test:
|
||||||
|
debug.out(50, "YYYY[-MM-DD]", answer, True, 2, True)
|
||||||
|
|
||||||
|
if answer != date:
|
||||||
|
tools.update_ini_file(domain.dcf_uri, "DOMAIN", "date", answer)
|
||||||
|
|
||||||
|
|
||||||
|
#========================#
|
||||||
|
# Get domain description #
|
||||||
|
#------------------------#
|
||||||
|
def ask_domain_about():
|
||||||
|
domain.dcf_load()
|
||||||
|
about = domain.dcf.get("DOMAIN", "about")
|
||||||
|
|
||||||
|
q = "> %s (%s)%s "%(langs.logs.domain_about, shorter(about), langs.logs.q)
|
||||||
|
answer = ask(q, False, about)
|
||||||
|
if answer != about:
|
||||||
|
tools.update_ini_file(domain.dcf_uri, "DOMAIN", "about", answer)
|
||||||
|
|
||||||
|
|
||||||
|
#=======================#
|
||||||
|
# Get domain admin mail #
|
||||||
|
#-----------------------#
|
||||||
|
def ask_domain_mail():
|
||||||
|
domain.dcf_load()
|
||||||
|
mail = domain.dcf.get("DOMAIN", "mail")
|
||||||
|
|
||||||
|
q = "> %s (%s)%s "%(langs.logs.domain_mail, shorter(mail), langs.logs.q)
|
||||||
|
answer = ask(q, False, mail)
|
||||||
|
if answer != mail:
|
||||||
|
tools.update_ini_file(domain.dcf_uri, "DOMAIN", "mail", answer)
|
||||||
|
|
||||||
|
|
||||||
|
#===============================================#
|
||||||
|
# Get domain tags (wil be used in all articles) #
|
||||||
|
#-----------------------------------------------#
|
||||||
|
def ask_domain_tags():
|
||||||
|
domain.dcf_load()
|
||||||
|
tags = domain.dcf.get("DOMAIN", "tags")
|
||||||
|
|
||||||
|
q = "> %s (%s)%s "%(langs.logs.domain_tags, shorter(tags), langs.logs.q)
|
||||||
|
answer = ask(q, False, tags)
|
||||||
|
|
||||||
|
if answer != tags:
|
||||||
|
# Remove useless spaces for HTML meta
|
||||||
|
tuple_tags = answer.rsplit(",")
|
||||||
|
answer = ""
|
||||||
|
for i, tag in enumerate(tuple_tags):
|
||||||
|
answer = answer + tag.strip()
|
||||||
|
if i != len(tuple_tags) - 1:
|
||||||
|
answer = answer + ","
|
||||||
|
|
||||||
|
tools.update_ini_file(domain.dcf_uri, "DOMAIN", "tags", answer)
|
||||||
|
|
||||||
|
|
||||||
|
#===================================#
|
||||||
|
# Get domain lang #
|
||||||
|
# default en if no translation file # > !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! < TODO
|
||||||
|
#-----------------------------------#
|
||||||
|
def ask_domain_lang():
|
||||||
|
domain.dcf_load()
|
||||||
|
lang = domain.dcf.get("WEBSITE", "lang") or langs.get_sys_lang()
|
||||||
|
|
||||||
|
q = "> %s (%s)%s "%(langs.logs.domain_lang, lang, langs.logs.q)
|
||||||
|
answer = ask(q, False, lang).lower()
|
||||||
|
|
||||||
|
# Lang Format is 2 character
|
||||||
|
if len(answer) != 2:
|
||||||
|
debug.out("8", "xx", answer, True, 2, False)
|
||||||
|
ask_domain_lang()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Check if translation file exists
|
||||||
|
if not langs.translation_exists("website", answer, False):
|
||||||
|
debug.out(103, "en", "%swebsite_en.py"%langs.trfs, True, 1, False)
|
||||||
|
answer = "en"
|
||||||
|
|
||||||
|
if answer != lang:
|
||||||
|
tools.update_ini_file(domain.dcf_uri, "WEBSITE", "lang", answer)
|
||||||
|
|
||||||
|
|
||||||
|
#===================================#
|
||||||
|
# Get domain server root #
|
||||||
|
#-----------------------------------#
|
||||||
|
def ask_domain_server():
|
||||||
|
domain.dcf_load()
|
||||||
|
srv = domain.dcf.get("SERVER", "root")
|
||||||
|
|
||||||
|
if srv:
|
||||||
|
if not tools.dir_exists(srv, False):
|
||||||
|
tested = True
|
||||||
|
srv = ""
|
||||||
|
|
||||||
|
q = "> %s (%s)%s "%(langs.logs.domain_srv, srv, langs.logs.q)
|
||||||
|
answer = ask(q, False, srv)
|
||||||
|
|
||||||
|
# Check if directory exists
|
||||||
|
if not tools.dir_exists(answer, False):
|
||||||
|
answer = srv
|
||||||
|
ask_domain_server()
|
||||||
|
return
|
||||||
|
|
||||||
|
domain.dcf_update_values(answer)
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Tyto - Littérateur
|
||||||
|
|
||||||
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# XMPP: echolib (im@echolib.re)
|
||||||
|
#
|
||||||
|
# Description: Show help commands
|
||||||
|
# File: /var/lib/tyto/program/help.py
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-------------------------
|
||||||
|
# Funny Stats Project
|
||||||
|
#-------------------------
|
||||||
|
# file lines :
|
||||||
|
# file comments :
|
||||||
|
# file functions:
|
||||||
|
# file program :
|
||||||
|
#--------------------------
|
||||||
|
|
||||||
|
import langs, debug
|
||||||
|
|
||||||
|
|
||||||
|
#==========================================#
|
||||||
|
# Show help in system langage #
|
||||||
|
# Help Contents is in translations/logs_XX #
|
||||||
|
#------------------------------------------#
|
||||||
|
def show(action, target):
|
||||||
|
print(langs.logs.help_contents)
|
|
@ -1,544 +0,0 @@
|
||||||
# Tyto - Littérateur
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License
|
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# XMPP: echolib (im@echolib.re)
|
|
||||||
#
|
|
||||||
# Description: Create HTML page
|
|
||||||
# File: /var/lib/tyto/program/html.py
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#-------------------------
|
|
||||||
# Funny Stats Project
|
|
||||||
#-------------------------
|
|
||||||
# file lines : 544
|
|
||||||
# file comments : 71
|
|
||||||
# file functions: 8
|
|
||||||
# file program : 414
|
|
||||||
#--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
import os, sys, importlib
|
|
||||||
import logs, db, dom, tyto, form, langs
|
|
||||||
|
|
||||||
|
|
||||||
# Publish option can be
|
|
||||||
wip_opts = ('wip', 'new')
|
|
||||||
pub_opts = ('www', 'pub')
|
|
||||||
|
|
||||||
# Not a line if it starts with...(for sidebar, navbar)
|
|
||||||
nolines = ('#', '/')
|
|
||||||
|
|
||||||
# For static modules
|
|
||||||
if dom.ready:
|
|
||||||
tags_html_mods = \
|
|
||||||
{
|
|
||||||
dom.wip_navbar_f : '<!--# include virtual="/template/navbar.html"-->',
|
|
||||||
dom.wip_sidebar_f : '<!--# include virtual="/template/sidebar.html"-->',
|
|
||||||
dom.wip_metas_f : '<!--# include virtual="/template/metas.html"-->',
|
|
||||||
dom.wip_footer_f : '<!--# include virtual="/template/footer.html"-->'
|
|
||||||
}
|
|
||||||
|
|
||||||
#==========================#
|
|
||||||
# Load article DB #
|
|
||||||
# Start HTML page sections #
|
|
||||||
#--------------------------#
|
|
||||||
def set_page(target, article_bottom):
|
|
||||||
create_metas_page() # Include metas tags
|
|
||||||
create_main_page(target, article_bottom) # Create main page
|
|
||||||
|
|
||||||
|
|
||||||
#============================================#
|
|
||||||
# Set metas_page to be included in main page #
|
|
||||||
#--------------------------------------------#
|
|
||||||
def create_metas_page():
|
|
||||||
global metas_page
|
|
||||||
|
|
||||||
# Settings for metas
|
|
||||||
#-------------------
|
|
||||||
metas_page = ''
|
|
||||||
scale = 'width=device-width, initial-scale=1.0'
|
|
||||||
all_tags = dom.tags + ',' + db.meta_tags
|
|
||||||
css_ref = 'href="%stemplate/%s"'%(db.sub_uri, dom.styles)
|
|
||||||
rss_ref = 'type="application/rss+xml" ' + \
|
|
||||||
'href="%s%s" title="RSS 2.0. %s %s %s"'%(
|
|
||||||
db.sub_uri, dom.rss,
|
|
||||||
dom.title, dom.sep, dom.shortname
|
|
||||||
)
|
|
||||||
icon_ref = 'type="image/png" href="%stemplate/%s"'%(
|
|
||||||
db.sub_uri, dom.favicon
|
|
||||||
)
|
|
||||||
relme = '' # External URL in metas (if exists in config domain)
|
|
||||||
if dom.relme:
|
|
||||||
relme = '\n <link rel="me" type="text/html" href="%s">'%(
|
|
||||||
dom.relme
|
|
||||||
)
|
|
||||||
|
|
||||||
# Create author and date publish section infos
|
|
||||||
create_html_time_meta('wip')
|
|
||||||
|
|
||||||
# Set all raw HTML metas
|
|
||||||
#-----------------------
|
|
||||||
global metas
|
|
||||||
metas = \
|
|
||||||
tags_html_mods[dom.wip_metas_f] + '\n' + \
|
|
||||||
' <meta name="viewport" content="%s">\n'%scale + \
|
|
||||||
' <meta name=”url” content=”%s”>\n'%dom.www_url + \
|
|
||||||
' <meta name="language" content="%s">\n'%dom.lang_site + \
|
|
||||||
' <meta name="reply-to" content="%s">\n'%dom.mail + \
|
|
||||||
' <meta name="copyright" content="%s">\n'%dom.license + \
|
|
||||||
' <meta name="generator" content="%s">\n'%tyto.Tyto + \
|
|
||||||
' <meta name="title" content="%s">\n'%db.title + \
|
|
||||||
' <meta name="author" content="%s">\n'%db.author + \
|
|
||||||
' <meta name="description" content="%s">\n'%db.about + \
|
|
||||||
' <meta name="keywords" content="%s">\n'%all_tags + \
|
|
||||||
'%s'%meta_pub + \
|
|
||||||
' <link rel="canonical" href="%s">\n'%db.http_www + \
|
|
||||||
' <link rel="alternate" %s>\n'%(rss_ref) + \
|
|
||||||
' <link rel="stylesheet" %s>\n'%css_ref + \
|
|
||||||
' <link rel="shortcut icon" %s>\n'%icon_ref + \
|
|
||||||
' <!-- Open Graph data -->\n' + \
|
|
||||||
' <meta property="og:site_name" content="%s">\n'%dom.title + \
|
|
||||||
' <meta property="og:title" content="%s">\n'%db.title + \
|
|
||||||
' <meta property="og:type" content="article">\n' + \
|
|
||||||
' <meta property="og:url" content="%s">\n'%db.http_www + \
|
|
||||||
' <meta property="og:description" content="%s">\n'%db.about + \
|
|
||||||
' <meta property="og:image" content="%s">\n'%db.snpic + \
|
|
||||||
'%s'%relme + \
|
|
||||||
' <title>%s %s %s</title>'%(db.title, dom.sep, dom.title)
|
|
||||||
|
|
||||||
|
|
||||||
#=======================================#
|
|
||||||
# Set main page, with all HTML sections #
|
|
||||||
#---------------------------------------#
|
|
||||||
def create_main_page(target, article_bottom):
|
|
||||||
global main_page, post_html_code
|
|
||||||
|
|
||||||
# Create link for website's logo
|
|
||||||
#-------------------------------
|
|
||||||
logo_html = \
|
|
||||||
'<a href="/"\n' + \
|
|
||||||
'%stitle="%s %s logo: %s"\n'%(11 * " ",
|
|
||||||
langs.site.home, dom.sep, dom.title
|
|
||||||
) + \
|
|
||||||
'%sid="site_logo_link">\n'%(11 * " ") + \
|
|
||||||
'%s<img src="%stemplate/%s"\n'%(
|
|
||||||
10 * " ", db.sub_uri, dom.logo
|
|
||||||
) + \
|
|
||||||
'%salt="logo: %s"\n'%(15 * " ", dom.title) + \
|
|
||||||
'%sid="site_logo_image">\n'%(15 * " ") + \
|
|
||||||
'%s</a>'%(8 * " ")
|
|
||||||
|
|
||||||
post_html_code = ''
|
|
||||||
if dom.article_code:
|
|
||||||
post_html_code = \
|
|
||||||
' <span id="article_code"> \n' + \
|
|
||||||
' <a id="article_code_link"\n' + \
|
|
||||||
' href="./%s"\n'%os.path.basename(db.short_src) + \
|
|
||||||
' title="%s [%s]">{%s}</a></span> \n'%(
|
|
||||||
langs.site.tyto_psrc, db.title,
|
|
||||||
langs.site.source_code
|
|
||||||
)
|
|
||||||
|
|
||||||
#-----------------------#
|
|
||||||
# Create main HTML Page #
|
|
||||||
#-----------------------#
|
|
||||||
main_page = \
|
|
||||||
'<!Doctype html>\n' + \
|
|
||||||
'<html lang="%s">\n'%dom.lang_site + \
|
|
||||||
' <head>\n' + \
|
|
||||||
'%s\n'%metas + \
|
|
||||||
' </head>\n\n' + \
|
|
||||||
' <body>\n' + \
|
|
||||||
' <div id="site_container">\n' + \
|
|
||||||
' <header id="header_page">\n' + \
|
|
||||||
' <div id="site_logo">\n' + \
|
|
||||||
' %s\n'%logo_html + \
|
|
||||||
' </div>\n' + \
|
|
||||||
' <div id="site_infos">\n' + \
|
|
||||||
' <h1 id="site_title">\n' + \
|
|
||||||
' <a href="/"\n' + \
|
|
||||||
' title="%s"\n'%(langs.site.home) + \
|
|
||||||
' id="site_link">%s</a>\n'%dom.title + \
|
|
||||||
' </h1>\n' + \
|
|
||||||
' <p id="site_about">%s</p>\n'%dom.about + \
|
|
||||||
' </div>\n' + \
|
|
||||||
' </header>\n' + \
|
|
||||||
tags_html_mods[dom.wip_navbar_f] + '\n' + \
|
|
||||||
' <div id="article_sidebar_container">\n' + \
|
|
||||||
' <article id="article_main">\n' + \
|
|
||||||
' <h1 accesskey="t" id="post_title"\n' + \
|
|
||||||
' title="[%s] %s %s %s %s">%s</h1>\n'%(
|
|
||||||
db.title, langs.site.w_written, db.date,
|
|
||||||
langs.site.by, db.author,
|
|
||||||
db.title,
|
|
||||||
) + \
|
|
||||||
'%s\n'%article_bottom + \
|
|
||||||
' <div id="article_infos">\n' + \
|
|
||||||
' <p>\n' + \
|
|
||||||
' <span id="article_author"\n' + \
|
|
||||||
' title="%s %s [%s]">%s</span>, %s\n'%(
|
|
||||||
db.author, langs.site.author_of, db.title,
|
|
||||||
db.author, langs.site.le
|
|
||||||
) + \
|
|
||||||
'%s\n'%time_html_pub + \
|
|
||||||
'%s'%post_html_code + \
|
|
||||||
' </p>\n' + \
|
|
||||||
' </div>\n' + \
|
|
||||||
' </article>\n' + \
|
|
||||||
'\n' + \
|
|
||||||
tags_html_mods[dom.wip_sidebar_f] + '\n' + \
|
|
||||||
' </div>\n' + \
|
|
||||||
tags_html_mods[dom.wip_footer_f] + '\n' + \
|
|
||||||
' </div>\n' + \
|
|
||||||
' </body>\n' + \
|
|
||||||
'</html>'
|
|
||||||
|
|
||||||
|
|
||||||
#============================================#
|
|
||||||
# Create HTML line for article infos section #
|
|
||||||
# when wip, and publish #
|
|
||||||
#--------------------------------------------#
|
|
||||||
def create_html_time_meta(process):
|
|
||||||
# Need to reload the DB to get last time updated
|
|
||||||
importlib.reload(db)
|
|
||||||
|
|
||||||
global time_html_pub, meta_pub, date_raw
|
|
||||||
|
|
||||||
if process == 'wip':
|
|
||||||
try:
|
|
||||||
date_raw = db.date_wip # <time datetime= / meta search_date
|
|
||||||
date_pub = db.date_wip.rsplit(' ')[0]
|
|
||||||
time_pub = db.date_wip.rsplit(' ')[1]
|
|
||||||
except:
|
|
||||||
logs.out("23", '"date_wip = ?" > %s'%db.uri_file, True)
|
|
||||||
|
|
||||||
elif process == 'publish':
|
|
||||||
try:
|
|
||||||
date_raw = db.date_www # <time datetime=
|
|
||||||
date_pub = db.date_www.rsplit(' ')[0]
|
|
||||||
time_pub = db.date_www.rsplit(' ')[1]
|
|
||||||
except:
|
|
||||||
logs.out("23", '"date_www = ?" > %s'%db.uri_file, True)
|
|
||||||
|
|
||||||
if dom.lang_site == 'fr':
|
|
||||||
date_new = date_pub.rsplit('-')
|
|
||||||
date_pub = date_new[2] + '/' + date_new[1] + '/' + date_new[0]
|
|
||||||
|
|
||||||
# in <article> > section info : line with new date
|
|
||||||
time_html_pub = \
|
|
||||||
'<!--Tyto_Published-->\n' + \
|
|
||||||
' <time datetime="%s">\n'%date_raw + \
|
|
||||||
' <span id="article_pub"\n' + \
|
|
||||||
' title="[%s] %s %s (%s)">%s</span>\n'%(
|
|
||||||
db.title, langs.site.w_published, date_pub, time_pub,
|
|
||||||
db.date
|
|
||||||
) + \
|
|
||||||
' </time>\n' + \
|
|
||||||
'<!--/Tyto_Published-->'
|
|
||||||
|
|
||||||
# meta search_date=
|
|
||||||
meta_pub = \
|
|
||||||
'<!--Tyto_Meta--> <meta name="search_date" content="%s">\n'%(
|
|
||||||
date_raw.rsplit(' ')[0]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
#=================================================#
|
|
||||||
# Create metas.html from _configs/tyto.metas.html #
|
|
||||||
# Opiton 'pub' force create (when publish) #
|
|
||||||
#-------------------------------------------------#
|
|
||||||
def create_user_metas(option):
|
|
||||||
dom.valid()
|
|
||||||
|
|
||||||
form.create_metas(option)
|
|
||||||
|
|
||||||
if option in wip_opts: target = dom.wip_metas_f
|
|
||||||
elif option in pub_opts: target = dom.www_metas_f
|
|
||||||
|
|
||||||
if option == 'www' and tyto.exists(target):
|
|
||||||
form.asking(' ├ %s. %s%s '%(
|
|
||||||
langs.site.metas, langs.site.form_rep, langs.site.q
|
|
||||||
), True)
|
|
||||||
|
|
||||||
# Create wip metas.html file according to option
|
|
||||||
#-----------------------------------------------
|
|
||||||
try: user_file = open(dom.metas_f, 'r').read()
|
|
||||||
except: logs.out("1", dom.metas_f, True)
|
|
||||||
|
|
||||||
user_metas = ''
|
|
||||||
tab = 4 * ' '
|
|
||||||
metas_used = ('<meta ', '<link ')
|
|
||||||
for line in user_file.rsplit('\n'):
|
|
||||||
if line.startswith(metas_used):
|
|
||||||
if user_metas: user_metas = "%s\n%s%s"%(user_metas, tab, line)
|
|
||||||
else: user_metas = '%s%s'%(tab, line)
|
|
||||||
|
|
||||||
tyto.set_file(target, 'New', user_metas)
|
|
||||||
|
|
||||||
|
|
||||||
#==============================================#
|
|
||||||
# Create HTML sidebar from file tyto.navbar #
|
|
||||||
# If no index file in src directory: pass # #
|
|
||||||
# Create empty file in template/ if not exists #
|
|
||||||
#----------------------------------------------#
|
|
||||||
def create_navbar(option):
|
|
||||||
dom.valid()
|
|
||||||
|
|
||||||
form.create_navbar(option)
|
|
||||||
|
|
||||||
if not tyto.exists(dom.navbar_f):
|
|
||||||
logs.out("1", dom.navbar_f, True)
|
|
||||||
|
|
||||||
if option in wip_opts: target = dom.wip_navbar_f
|
|
||||||
elif option in pub_opts: target = dom.www_navbar_f
|
|
||||||
|
|
||||||
if option == 'www' and tyto.exists(target):
|
|
||||||
form.asking(' ├ %s. %s(%s)%s '%(
|
|
||||||
langs.site.navbar, langs.site.form_rep,
|
|
||||||
option, langs.site.q
|
|
||||||
), True)
|
|
||||||
|
|
||||||
# navbar has items
|
|
||||||
navbar_items = False
|
|
||||||
|
|
||||||
# Set first HTML line
|
|
||||||
menu_html = \
|
|
||||||
'%s<nav accesskey="m" id="site_menu">\n'%(4 * ' ') + \
|
|
||||||
'%s<menu id="site_menu_items">'%(6 * ' ')
|
|
||||||
|
|
||||||
navbar_lines = open(dom.navbar_f, 'r').read()
|
|
||||||
|
|
||||||
for line in navbar_lines.rsplit('\n'):
|
|
||||||
if not line or line.startswith(nolines): continue
|
|
||||||
|
|
||||||
# Get HTML title if defined (commented after)
|
|
||||||
if '#' in line:
|
|
||||||
direc = line.rsplit('#')[0].rstrip()
|
|
||||||
title = '%stitle="%s"\n'%(15 * ' ', line.rsplit('#')[1].lstrip())
|
|
||||||
else:
|
|
||||||
direc = line
|
|
||||||
title = ''
|
|
||||||
|
|
||||||
# Check if directory exists in articles/
|
|
||||||
dir_uri = os.path.join(dom.articles_d, direc)
|
|
||||||
if not os.path.isdir(dir_uri):
|
|
||||||
logs.out("24", '%s/'%dir_uri, False)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Check if an index.[ext] exists (src, wip, www)
|
|
||||||
no_wip_index = False
|
|
||||||
no_www_index = False
|
|
||||||
src_index = ''
|
|
||||||
wip_index = '%s%s/index.html'%(dom.srv_wip, direc)
|
|
||||||
www_index = '%s%s/index.html'%(dom.srv_www, direc)
|
|
||||||
|
|
||||||
# Source index article must exist
|
|
||||||
src_index = [ \
|
|
||||||
filename \
|
|
||||||
for filename in os.listdir(dir_uri) \
|
|
||||||
if filename.startswith("index.") \
|
|
||||||
and os.path.isfile \
|
|
||||||
]
|
|
||||||
if not src_index:
|
|
||||||
src_index = '%s%s/index.tyto'%(dom.articles_d, direc)
|
|
||||||
logs.out('26', '> %s'%(src_index), False)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# index.html server files must exist (or 404 error)
|
|
||||||
if option in wip_opts:
|
|
||||||
if not tyto.exists(wip_index):
|
|
||||||
logs.out('26', '> %s'%(wip_index), False)
|
|
||||||
no_wip_index = True
|
|
||||||
continue
|
|
||||||
|
|
||||||
elif option in pub_opts:
|
|
||||||
if not tyto.exists(www_index):
|
|
||||||
logs.out('26', '> %s'%(www_index), False)
|
|
||||||
no_www_index = True
|
|
||||||
continue
|
|
||||||
|
|
||||||
|
|
||||||
# Add link to HTML structure
|
|
||||||
navbar_items = True
|
|
||||||
menu_item = \
|
|
||||||
'\n%s<li class="site_menu_item">\n'%(8 * ' ') + \
|
|
||||||
'%s<a class="site_menu_link"\n'%(10 * ' ') + \
|
|
||||||
'%s'%title + \
|
|
||||||
'%shref="/%s/">%s</a>\n'%(
|
|
||||||
15 * ' ', direc, direc
|
|
||||||
) + \
|
|
||||||
'%s</li>'%(8 * ' ')
|
|
||||||
|
|
||||||
menu_html = '%s%s'%(menu_html, menu_item)
|
|
||||||
|
|
||||||
|
|
||||||
# Nothing to do
|
|
||||||
if not navbar_items:
|
|
||||||
tyto.set_file(target, 'New', '')
|
|
||||||
|
|
||||||
# Create ending HTML file
|
|
||||||
else:
|
|
||||||
menu_html = '\n%s\n%s</menu>\n%s</nav>\n'%(menu_html, 6 * ' ', 4 * ' ')
|
|
||||||
tyto.set_file(target, 'New', menu_html)
|
|
||||||
|
|
||||||
|
|
||||||
#==============================================#
|
|
||||||
# Create HTML sidebar from file tyto.sidebar #
|
|
||||||
# Create empty file in template/ if not exists #
|
|
||||||
#----------------------------------------------#
|
|
||||||
def create_sidebar(option):
|
|
||||||
dom.valid()
|
|
||||||
|
|
||||||
form.create_sidebar(option)
|
|
||||||
|
|
||||||
if not tyto.exists(dom.sidebar_f):
|
|
||||||
logs.out("1", dom.sidebar_f, True)
|
|
||||||
|
|
||||||
if int(dom.sidebar_items) > 16: db.sidebar_items = 6
|
|
||||||
|
|
||||||
if option in wip_opts: target = dom.wip_sidebar_f
|
|
||||||
elif option in pub_opts: target = dom.www_sidebar_f
|
|
||||||
|
|
||||||
if option == 'www' and tyto.exists(target):
|
|
||||||
form.asking(' ├ %s. %s%s '%(
|
|
||||||
langs.site.sidebar, langs.site.form_rep, langs.site.q
|
|
||||||
), True)
|
|
||||||
|
|
||||||
sidebar_items = False
|
|
||||||
|
|
||||||
# Set HTML sidebar
|
|
||||||
sidebar_list = ''
|
|
||||||
sidebar_html = \
|
|
||||||
'<aside accesskey="s" id="sidebar">\n' + \
|
|
||||||
' <h2 id="sidebar_title">%s</h2>\n' + \
|
|
||||||
' <ul id="sidebar_list">\n' + \
|
|
||||||
'%s' + \
|
|
||||||
' </ul>\n' + \
|
|
||||||
'</aside>'
|
|
||||||
|
|
||||||
sidebar_title = dom.sidebar_title
|
|
||||||
sidebar_lines = open(dom.sidebar_f, 'r').read()
|
|
||||||
|
|
||||||
counter = 0
|
|
||||||
for line in sidebar_lines.rsplit('\n'):
|
|
||||||
if not line or line.startswith(nolines):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if line.startswith(':'):
|
|
||||||
sidebar_title = line.rsplit(':')[1].lstrip()
|
|
||||||
continue
|
|
||||||
|
|
||||||
f_uri = '%s%s'%(dom.articles_d, line)
|
|
||||||
if not tyto.exists(f_uri):
|
|
||||||
logs.out("24", f_uri, False)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Get Hash from uri to get db file
|
|
||||||
hash_uri = tyto.get_filesum(f_uri, False)
|
|
||||||
db_uri = '%s%s.config'%(dom.articles_db_d, hash_uri)
|
|
||||||
if not tyto.exists(db_uri):
|
|
||||||
logs.out('25', line, False)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Load article"s database
|
|
||||||
exec(open(db_uri).read(),globals())
|
|
||||||
|
|
||||||
# Check wip status and if article exists in server
|
|
||||||
if option in wip_opts:
|
|
||||||
if hash_wip != hash_chk:
|
|
||||||
logs.out("30", line, False)
|
|
||||||
continue
|
|
||||||
if not tyto.exists(post_wip):
|
|
||||||
logs.out("24", post_wip, False)
|
|
||||||
continue
|
|
||||||
|
|
||||||
elif option in pub_opts:
|
|
||||||
if hash_www != hash_chk:
|
|
||||||
logs.out("30", line, False)
|
|
||||||
continue
|
|
||||||
if not tyto.exists(post_www):
|
|
||||||
logs.out("24", post_www, False)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Add item if not max
|
|
||||||
sidebar_items = True
|
|
||||||
counter += 1
|
|
||||||
if counter > dom.sidebar_items: break
|
|
||||||
|
|
||||||
# Show item to add
|
|
||||||
logs.out("35", '"%s" > %s'%(title, line), False)
|
|
||||||
|
|
||||||
# Create HTML list for this article
|
|
||||||
link_title = '%s [%s]'%(title, author)
|
|
||||||
sidebar_list = sidebar_list + \
|
|
||||||
' <li class="sidebar_item">\n' + \
|
|
||||||
' <a class="sidebar_item_link"\n' + \
|
|
||||||
' href="/%s">\n'%short_srv + \
|
|
||||||
' <h3 class="sidebar_item_title">%s</h3>\n'%title + \
|
|
||||||
' <p class="sidebar_item_about"\n' + \
|
|
||||||
' title="%s">\n'%link_title + \
|
|
||||||
' %s - %s\n'%(date, about) + \
|
|
||||||
' </p>\n' + \
|
|
||||||
' </a>\n' + \
|
|
||||||
' </li>\n'
|
|
||||||
|
|
||||||
# Nothing to do
|
|
||||||
if not sidebar_items:
|
|
||||||
tyto.set_file(target, 'New', '')
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Create HTML complete sidebar
|
|
||||||
sidebar_temp = sidebar_html%(sidebar_title, sidebar_list)
|
|
||||||
|
|
||||||
# Indent HTML code
|
|
||||||
sidebar_content = ''
|
|
||||||
for line in sidebar_temp.rsplit('\n'):
|
|
||||||
sidebar_content = sidebar_content + '%s%s\n'%(4 * ' ', line)
|
|
||||||
|
|
||||||
tyto.set_file(target, True, sidebar_content)
|
|
||||||
|
|
||||||
|
|
||||||
#===================================================#
|
|
||||||
# Create footer.html from _configs/tyto.footer.html #
|
|
||||||
#----------------------------------------------=====#
|
|
||||||
def create_user_footer(option):
|
|
||||||
dom.valid()
|
|
||||||
|
|
||||||
form.create_footer(option)
|
|
||||||
|
|
||||||
if option in wip_opts: target = dom.wip_footer_f
|
|
||||||
elif option in pub_opts: target = dom.www_footer_f
|
|
||||||
|
|
||||||
if option == 'www' and tyto.exists(target):
|
|
||||||
form.asking(' ├ %s. %s%s '%(
|
|
||||||
langs.site.footer, langs.site.form_rep, langs.site.q
|
|
||||||
), True)
|
|
||||||
|
|
||||||
try: footer_f = open(dom.footer_f, 'r').read()
|
|
||||||
except: logs.out("1", dom.footer_f, True)
|
|
||||||
|
|
||||||
footer = ''
|
|
||||||
tab = 4 * ' '
|
|
||||||
for line in footer_f.rsplit('\n'):
|
|
||||||
if not line or line.startswith('#'): continue
|
|
||||||
|
|
||||||
if footer: footer = "%s\n%s%s"%(footer, tab, line)
|
|
||||||
else: footer = '%s%s'%(tab, line)
|
|
||||||
|
|
||||||
tyto.set_file(target, 'New', footer)
|
|
||||||
|
|
|
@ -1,131 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Tyto - Littérateur
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License
|
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# XMPP: echolib (im@echolib.re)
|
|
||||||
#
|
|
||||||
# Description: Show helps and informations
|
|
||||||
# File: /var/lib/tyto/program/infos.py
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#-------------------------
|
|
||||||
# Funny Stats Project
|
|
||||||
#-------------------------
|
|
||||||
# file lines : 131
|
|
||||||
# file comments : 27
|
|
||||||
# file functions: 3
|
|
||||||
# file program : 91
|
|
||||||
#--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
import os, sys, importlib
|
|
||||||
import langs
|
|
||||||
importlib.reload(langs)
|
|
||||||
|
|
||||||
|
|
||||||
# Set colors
|
|
||||||
CS = '\033[0;0m'
|
|
||||||
CR = '\033[1;31m'
|
|
||||||
CY = '\033[1;33m'
|
|
||||||
CG = '\033[1;32m'
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Show Version
|
|
||||||
#
|
|
||||||
def version():
|
|
||||||
# Show Version
|
|
||||||
tytobin = open('/usr/bin/tyto').read()
|
|
||||||
for line in tytobin.rsplit('\n'):
|
|
||||||
if line.startswith('# Version:'):
|
|
||||||
print(line)
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
#==========================================#
|
|
||||||
# List all found domain in local directory #
|
|
||||||
#------------------------------------------"
|
|
||||||
def list_domains():
|
|
||||||
# Show domains list
|
|
||||||
try:
|
|
||||||
has_domains = True
|
|
||||||
user = os.environ.get('USER')
|
|
||||||
user_dir = os.path.expanduser('~')
|
|
||||||
db_domains = '%s/.local/tyto'%user_dir
|
|
||||||
except:
|
|
||||||
has_domains = False
|
|
||||||
|
|
||||||
if not os.path.exists(db_domains):
|
|
||||||
has_domains = False
|
|
||||||
print('! No directory > %s/'%db_domains)
|
|
||||||
|
|
||||||
if has_domains:
|
|
||||||
for folder in os.listdir(db_domains):
|
|
||||||
domain_local_uri = '%s/%s'%(db_domains, folder)
|
|
||||||
|
|
||||||
if os.path.isdir(domain_local_uri):
|
|
||||||
line = ' - %s >'%folder
|
|
||||||
|
|
||||||
# Check configuration file and load
|
|
||||||
domain_conf = '%s/domain_config.bkp'%domain_local_uri
|
|
||||||
if not os.path.exists(domain_conf):
|
|
||||||
line = '%s %sUnknown%s ?'%(line, CR, CS)
|
|
||||||
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
exec(open(domain_conf).read(),globals())
|
|
||||||
line = '%s %sConfig%s > '%(line, CG, CS)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
if os.path.exists(directory):
|
|
||||||
line = '%s %s%s%s'%(line, CG, directory, CS)
|
|
||||||
else:
|
|
||||||
line = '%s %s%s%s'%(line, CR, directory, CS)
|
|
||||||
except:
|
|
||||||
line = '%s %sNo root%s > '%(line, CR, CS)
|
|
||||||
|
|
||||||
try:
|
|
||||||
line = '%s %s'%(line, www_url)
|
|
||||||
except:
|
|
||||||
line = '%s %sNo URL%s > '%(line, CR, CS)
|
|
||||||
|
|
||||||
print(line)
|
|
||||||
|
|
||||||
#
|
|
||||||
# --help [full]
|
|
||||||
#
|
|
||||||
def tyto(target):
|
|
||||||
if target == "full":
|
|
||||||
version()
|
|
||||||
list_domains()
|
|
||||||
print(langs.site.args_helps)
|
|
||||||
print(langs.site.ex_helps)
|
|
||||||
|
|
||||||
elif target == 'help':
|
|
||||||
print(langs.site.args_helps)
|
|
||||||
|
|
||||||
elif target == 'domains':
|
|
||||||
list_domains()
|
|
||||||
|
|
||||||
elif target == 'version':
|
|
||||||
version()
|
|
||||||
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
|
@ -1,90 +1,135 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Tyto - Littérateur
|
# Tyto - Littérateur
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License
|
# it under the terms of the GNU General Public License as published by
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# License, or of the License, or (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU Affero General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# XMPP: echolib (im@echolib.re)
|
# XMPP: echolib (im@echolib.re)
|
||||||
#
|
#
|
||||||
# Description: Load translations file for logs and forms/sites
|
# Description: Load lang logs file according to system language
|
||||||
|
# Load lang site file according to domain configuration
|
||||||
# File: /var/lib/tyto/program/langs.py
|
# File: /var/lib/tyto/program/langs.py
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
#-------------------------
|
#-------------------------
|
||||||
# Funny Stats Project
|
# Funny Stats Project
|
||||||
#-------------------------
|
#-------------------------
|
||||||
# file lines : 90
|
# file lines :
|
||||||
# file comments : 28
|
# file comments :
|
||||||
# file functions: 0
|
# file functions:
|
||||||
# file program : 53
|
# file program :
|
||||||
#--------------------------
|
#--------------------------
|
||||||
|
|
||||||
|
import sys, locale, os
|
||||||
import locale, sys, os, importlib
|
import args, debug, domain
|
||||||
import dom
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
trfs = "/var/lib/tyto/translations/"
|
||||||
site.yes
|
|
||||||
|
|
||||||
except:
|
#==================================#
|
||||||
# Import translation directory
|
# Check if translation file exists #
|
||||||
trans_dir = '/var/lib/tyto/translations'
|
# module: #
|
||||||
sys.path.insert(0, trans_dir)
|
# - "logs": logs_xx #
|
||||||
|
# - "website": website_xx #
|
||||||
|
# lang: 2 chars language #
|
||||||
|
# out: exit if True
|
||||||
|
# return True or False #
|
||||||
|
#----------------------------------#
|
||||||
|
def translation_exists(module, lang, out):
|
||||||
|
global tr_file
|
||||||
|
|
||||||
|
modules = ("logs", "website")
|
||||||
|
if not module in modules: return # in case of internal typo error
|
||||||
|
|
||||||
|
tr_file = "%s%s_%s.py"%(trfs, module, lang)
|
||||||
|
if not os.path.exists(tr_file):
|
||||||
|
debug.out(5, lang, tr_file, True, 2, out)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
#=============================================================================#
|
||||||
|
# LOGS | #
|
||||||
|
# Set and import file | #
|
||||||
|
#=============================================================================#
|
||||||
|
#=============================#
|
||||||
|
# Get system Lang to set logs #
|
||||||
|
#-----------------------------#
|
||||||
|
def get_sys_lang():
|
||||||
|
global lang, tr_logs_uri
|
||||||
|
|
||||||
|
tr_logs_uri = "%slogs_%s.py"
|
||||||
|
|
||||||
|
try: lang = locale.getdefaultlocale()[0].rsplit("_")[0]
|
||||||
|
except: lang = "en"
|
||||||
|
|
||||||
|
if not translation_exists("logs", lang, False):
|
||||||
|
lang = "en"
|
||||||
|
|
||||||
|
tr_logs_uri = tr_logs_uri%(trfs, lang)
|
||||||
|
|
||||||
|
return lang
|
||||||
|
|
||||||
|
|
||||||
|
#===============================#
|
||||||
|
# Import logs lang file in logs #
|
||||||
|
#-------------------------------#
|
||||||
|
def load_logs_lang():
|
||||||
|
global logs, lang, set_logs
|
||||||
|
|
||||||
# Create yes array with all yes languages
|
|
||||||
try:
|
try:
|
||||||
answer_yes
|
set_logs
|
||||||
except:
|
except:
|
||||||
answer_yes = (())
|
logs = __import__("logs_%s"%get_sys_lang())
|
||||||
for lang_file in os.listdir(trans_dir):
|
debug.out(201, lang, tr_logs_uri, False, 0, False)
|
||||||
if lang_file.startswith("site_") and lang_file.endswith(".py"):
|
set_logs = True
|
||||||
lang_file = lang_file.replace(".py", "")
|
|
||||||
|
|
||||||
lang = importlib.import_module(lang_file)
|
|
||||||
answer_yes = answer_yes + ((lang.yes),)
|
|
||||||
|
|
||||||
|
|
||||||
# Get default system language
|
#=============================================================================#
|
||||||
# or set "en" (english) if no translation file
|
# WEBSITE | #
|
||||||
|
# Get/Set and import file | #
|
||||||
|
#=============================================================================#
|
||||||
|
#=======================================#
|
||||||
|
# Get website lang from dcf to set site #
|
||||||
|
#---------------------------------------#
|
||||||
|
def get_website_lang():
|
||||||
|
global site_lang, tr_website_uri
|
||||||
|
|
||||||
|
tr_website_uri = "%swebsite_%s.py"
|
||||||
|
domain.dcf_load()
|
||||||
|
site_lang = domain.dcf.get("WEBSITE", "lang")
|
||||||
|
|
||||||
|
if not translation_exists("website", site_lang, False):
|
||||||
|
site_lang = get_sys_lang()
|
||||||
|
|
||||||
|
tr_website_uri = tr_website_uri%(trfs, site_lang)
|
||||||
|
|
||||||
|
return site_lang
|
||||||
|
|
||||||
|
|
||||||
|
#==================================#
|
||||||
|
# Import website lang file in site #
|
||||||
|
#----------------------------------#
|
||||||
|
def load_website_lang():
|
||||||
|
global site, site_lang, set_site
|
||||||
|
|
||||||
try:
|
try:
|
||||||
lang_sys = locale.getdefaultlocale()[0].split('_')[0]
|
set_site
|
||||||
os.path.exists('%s/logs_%s.py'%(trans_dir, lang_sys))
|
|
||||||
except:
|
except:
|
||||||
lang_sys = 'en'
|
site = __import__("website_%s"%get_website_lang())
|
||||||
|
debug.out(208, site_lang, tr_website_uri, False, 0, False)
|
||||||
|
set_site = True
|
||||||
# Set language logs from configuration domain
|
|
||||||
# or set default english if not known
|
|
||||||
try:
|
|
||||||
dom.exists
|
|
||||||
lang_logs = dom.lang_logs
|
|
||||||
os.path.exists('%s/logs_%s.py'%(trans_dir, lang_logs))
|
|
||||||
log = importlib.import_module('logs_%s'%lang_logs, package=None)
|
|
||||||
except:
|
|
||||||
log = importlib.import_module('logs_%s'%lang_sys, package=None)
|
|
||||||
|
|
||||||
|
|
||||||
# Set language site/form from configuration domain
|
|
||||||
# or set default english if not known
|
|
||||||
try:
|
|
||||||
dom.exists
|
|
||||||
lang_site = dom.lang_site
|
|
||||||
os.path.exists('%s/site_%s.py'%(trans_dir, lang_site))
|
|
||||||
site = importlib.import_module('site_%s'%lang_site, package=None)
|
|
||||||
except:
|
|
||||||
site = importlib.import_module('site_%s'%lang_sys, package=None)
|
|
||||||
|
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Tyto - Littérateur
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License
|
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# XMPP: echolib (im@echolib.re)
|
|
||||||
#
|
|
||||||
# Description: Show logs messages, exit with nbr
|
|
||||||
# File: /var/lib/tyto/program/logs.py
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#-------------------------
|
|
||||||
# Funny Stats Project
|
|
||||||
#-------------------------
|
|
||||||
# file lines : 127
|
|
||||||
# file comments : 23
|
|
||||||
# file functions: 1
|
|
||||||
# file program : 93
|
|
||||||
#--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
import os, sys
|
|
||||||
import langs
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
shebang
|
|
||||||
except:
|
|
||||||
# Use to mark new article
|
|
||||||
shebang = "#!/NEW"
|
|
||||||
|
|
||||||
# Set colors
|
|
||||||
CS = '\033[0;0m'
|
|
||||||
CR = '\033[1;31m'
|
|
||||||
CY = '\033[1;33m'
|
|
||||||
CG = '\033[1;32m'
|
|
||||||
|
|
||||||
|
|
||||||
# Exit from program with message #
|
|
||||||
#--------------------------------#
|
|
||||||
def out(nbr, value, out):
|
|
||||||
logs = {
|
|
||||||
'1' : ' ╞ %s%s%s > %s'%(CR, langs.log.unused_r, CS, value),
|
|
||||||
'2' : ' ╞ %s%s%s > %s'%(CR, langs.log.data_inc, CS, value),
|
|
||||||
'3' : ' ╞ %s%s%s %s'%(CR, langs.log.data_inv, CS, value),
|
|
||||||
'4' : ' ╘ %sUnable to create file%s: %s'%(CR, CS, value),
|
|
||||||
'5' : ' ╘ %s%s%s > "%s"'%(CR, langs.log.no_arg, CS, value),
|
|
||||||
'6' : ' ╞ %s%s%s > %s'%(CR, langs.log.sep_inv, CS, value),
|
|
||||||
'7' : ' ╘ %s%s%s > %s'%(CR, langs.log.post_inv, CS, value),
|
|
||||||
'8' : ' ╞ %s%s%s %s'%(CR, langs.log.mark_np, CS, value),
|
|
||||||
'9' : ' ╞ %s%s%s > %s'%(CR, langs.log.post_chg, CS, value),
|
|
||||||
'10' : ' ╘ %s%s%s'%(CR, langs.log.dom_no, CS),
|
|
||||||
'11' : ' ╘ %s%s%s > %s'%(CR, langs.log.err_arg, CS, value),
|
|
||||||
'12' : ' ╞ %s%s%s > %s'%(CR, langs.log.post_inc, CS, value),
|
|
||||||
'13' : ' ╞ %s%s%s'%(CR, langs.log.no_fidi, CS),
|
|
||||||
'14' : ' ╞ %sMismatch%s program start'%(CR, CS),
|
|
||||||
'15' : ' ╞ %s%s%s %s'%(CR, langs.log.anch_nu, CS, value),
|
|
||||||
'16' : ' ╞ %s%s%s "%s = ?"'%(CR, langs.log.unused_c, CS, value),
|
|
||||||
'17' : ' ╞ %s%s%s "%s ?"'%(CR, langs.log.unused_v, CS, value),
|
|
||||||
'18' : ' ╘ %s%s%s > %s'%(CR, langs.log.unused_p, CS, value),
|
|
||||||
'19' : ' ╞ %s%s%s %s'%(CG, langs.log.was_wip, CS, value),
|
|
||||||
'20' : ' ╞═ %s%s%s %s'%(CG, langs.log.was_chk, CS, value),
|
|
||||||
'21' : ' ╘ %s%s%s > %s'%(CG, langs.log.post_val, CS, value),
|
|
||||||
'22' : ' ╞ %s%s%s %s'%(CY, langs.log.symb_np, CS, value),
|
|
||||||
'23' : ' ╞ %s%s%s > %s'%(CY, langs.log.db_inv, CS, value),
|
|
||||||
'24' : ' ╞ %s%s%s > %s'%(CY, langs.log.unused_r, CS, value),
|
|
||||||
'25' : ' ╞═ %s%s%s > %s'%(CY, langs.log.nycheck, CS, value),
|
|
||||||
'26' : ' ╞ %s%s%s %s'%(CY, langs.log.nyfile, CS, value),
|
|
||||||
'27' : ' ╞ %s%s%s %s'%(CY, langs.log.snpic_d, CS, value),
|
|
||||||
'28' : ' ╘ %s (%s)'%(langs.log.ntd, value),
|
|
||||||
'29' : ' ╞ %sEmpty configuration%s %s'%(CY, CS, value),
|
|
||||||
'30' : ' ╞ %s%s%s > %s'%(CY, langs.log.nywip, CS, value),
|
|
||||||
'31' : ' ╘ %s%s%s'%(CR, langs.log.nomods, CS),
|
|
||||||
'32' : ' ╞══ %s%s%s > %s'%(CG, langs.log.file_c, CS, value),
|
|
||||||
'33' : ' ╞══ %s%s%s > %s'%(CG, langs.log.dir_c, CS, value),
|
|
||||||
'34' : ' ╞══ %s%s%s > %s'%(CG, langs.log.file_n, CS, value),
|
|
||||||
'35' : ' ╞═ %s%s%s %s'%(CG, langs.log.add, CS, value),
|
|
||||||
'36' : ' ╡ %s %s'%(langs.log.file_e, value),
|
|
||||||
'37' : ' ╡ %s %s'%(langs.log.dir_e, value),
|
|
||||||
'38' : ' ╞ %s%s%s "%s ?"'%(CR, langs.log.unused_t, CS, value),
|
|
||||||
'39' : ' ╒ %s%s%s > %s'%(CR, langs.log.dom_cor, CS, value),
|
|
||||||
'40' : ' ╒ %s%s%s > %s'%(CY, langs.log.dom_ina, CS, value),
|
|
||||||
'41' : ' ╒ %s%s%s > %s'%(CR, langs.log.dom_inc, CS, value),
|
|
||||||
'42' : ' ╒ %s%s%s > %s'%(CG, langs.log.dom_act, CS, value),
|
|
||||||
'43' : ' ╒ %s%s%s'%(CY, langs.log.dom_no, CS),
|
|
||||||
'44' : ' ╞ %s%s%s "tyto check %s"'%(CY, langs.log.check_m, CS, value),
|
|
||||||
'45' : ' ╞ %s%s %s%s > %s'%(CY, langs.log.meta_t, langs.log.no_up, CS, value),
|
|
||||||
'46' : ' ╞ %s%s %s%s > %s'%(CY, langs.log.time_t, langs.log.no_up, CS, value),
|
|
||||||
'51' : ' ╞ %s%s%s > %s'%(CY, langs.log.data_inc, CS, value),
|
|
||||||
'60' : ' │\n ╞ %s'%langs.log.status_r,
|
|
||||||
'61' : ' ╞ %s%s%s > %s'%(CG, langs.log.file_e, CS, value),
|
|
||||||
'85' : ' ╞═ %s%s%s > %s'%(CY, langs.log.was_pub, CS, value),
|
|
||||||
'81' : ' ╘ %s%s%s > %s'%(CR, langs.log.post_exists, CS, value),
|
|
||||||
'82' : ' ╞ %s%s "%s"%s > %s'%(CR, langs.log.shebang_r, shebang, CS, value),
|
|
||||||
'84' : ' ╞ %s%s%s %s'%(CR, langs.log.title_no, CS, value),
|
|
||||||
'91' : ' ╞═ %s%s%s > %s'%(CY, langs.log.post_nfd, CS, value),
|
|
||||||
'92' : ' ╞═ %s%s%s > %s'%(CG, langs.log.post_yfd, CS, value),
|
|
||||||
'94' : ' ╞═ %s%s%s > %s'%(CY, langs.log.st_chk_o, CS, value),
|
|
||||||
'95' : ' ╞═ %s%s%s > %s'%(CG, langs.log.status_s, CS, value),
|
|
||||||
'96' : ' ╞═ %s%s%s > %s'%(CY, langs.log.static_y, CS, value),
|
|
||||||
'97' : ' ╞═ %s%s%s > %s'%(CG, langs.log.static_n, CS, value),
|
|
||||||
'98' : ' ╞═ %s%s%s > %s'%(CY, langs.log.status_n, CS, value),
|
|
||||||
'99' : ' ╞═ %s%s%s > %s'%(CY, langs.log.status_o, CS, value),
|
|
||||||
'255' : ' ╘ %s'%langs.log.laterout
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = logs[nbr]
|
|
||||||
print(msg)
|
|
||||||
|
|
||||||
out_0 = (21, 28)
|
|
||||||
if int(nbr) in out_0: nbr = 0
|
|
||||||
if out: sys.exit(int(nbr))
|
|
||||||
|
|
|
@ -1,94 +1,61 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Tyto - Littérateur
|
# Tyto - Littérateur
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License
|
# it under the terms of the GNU General Public License as published by
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# License, or of the License, or (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU Affero General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# XMPP: echolib (im@echolib.re)
|
# XMPP: echolib (im@echolib.re)
|
||||||
#
|
#
|
||||||
# Description: Create something new (domain, sidebar...)
|
# Description: When user wants to create something new
|
||||||
# File: /var/lib/tyto/program/new.py
|
# File: /var/lib/tyto/program/new.py
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
#-------------------------
|
#-------------------------
|
||||||
# Funny Stats Project
|
# Funny Stats Project
|
||||||
#-------------------------
|
#-------------------------
|
||||||
# file lines : 94
|
# file lines :
|
||||||
# file comments : 27
|
# file comments :
|
||||||
# file functions: 1
|
# file functions:
|
||||||
# file program : 59
|
# file program :
|
||||||
#--------------------------
|
#--------------------------
|
||||||
|
|
||||||
|
import args, domain
|
||||||
import sys
|
|
||||||
from unidecode import unidecode
|
|
||||||
import args, dom, logs, langs, form, html, tyto, show, creators
|
|
||||||
|
|
||||||
|
|
||||||
#===============================================#
|
#====================================#
|
||||||
# manage argument new for #
|
# Manage arguments from command line #
|
||||||
# - domain: target becomes 3rd command argument #
|
# Specific to action "new" #
|
||||||
#-----------------------------------------------#
|
#------------------------------------#
|
||||||
def manage(target):
|
def manage(action, target):
|
||||||
# "domain" target
|
do = {
|
||||||
#----------------
|
"domain" : create_domain,
|
||||||
option = args.action
|
}
|
||||||
if target == "domain":
|
|
||||||
try: option = sys.argv[3]
|
|
||||||
except: option = args.action
|
|
||||||
|
|
||||||
if target in args.pass_targets:
|
do[target]()
|
||||||
actions = {
|
|
||||||
'domain' : form.manage,
|
|
||||||
'sidebar' : html.create_sidebar,
|
|
||||||
'navbar' : html.create_navbar,
|
|
||||||
'metas' : html.create_user_metas,
|
|
||||||
'footer' : html.create_user_footer,
|
|
||||||
'sitemap' : creators.manage
|
|
||||||
}
|
|
||||||
|
|
||||||
actions[target](option)
|
|
||||||
|
|
||||||
|
|
||||||
# article target name
|
|
||||||
#--------------------
|
|
||||||
else:
|
|
||||||
if args.target.endswith(".tyto"):
|
|
||||||
args.target = args.target.replace(".tyto", '')
|
|
||||||
|
|
||||||
# In case needed (todo later)
|
#===================================#
|
||||||
# u = unidecode(args.target, "utf-8")
|
# From command line "new domain" #
|
||||||
# args.target = unidecode(u)
|
# Create and set only if not exists #
|
||||||
|
# or if user "force" option
|
||||||
|
#-----------------------------------#
|
||||||
|
def create_domain():
|
||||||
|
if not domain.dcf_exists() or args.force:
|
||||||
|
domain.dcf_create()
|
||||||
|
return
|
||||||
|
|
||||||
filepost = "%s%s.tyto"%(dom.articles_d, args.target)
|
|
||||||
if tyto.exists(filepost):
|
|
||||||
logs.out("81", filepost, True)
|
|
||||||
|
|
||||||
else:
|
|
||||||
form.asking(" ├ %s%s {%s}%s "%(
|
|
||||||
langs.site.new_post,
|
|
||||||
langs.site.q,
|
|
||||||
filepost,
|
|
||||||
langs.site.q
|
|
||||||
), True)
|
|
||||||
|
|
||||||
post = tyto.new_article%(logs.shebang,
|
|
||||||
args.target,
|
|
||||||
dom.user,
|
|
||||||
tyto.nowdate().rsplit(' ')[0]
|
|
||||||
)
|
|
||||||
tyto.set_file(filepost, True, post)
|
|
||||||
show.read_lines(filepost, True)
|
|
||||||
|
|
|
@ -1,294 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Tyto - Littérateur
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License
|
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# XMPP: echolib (im@echolib.re)
|
|
||||||
#
|
|
||||||
# Description: Publish on www server
|
|
||||||
# File: /var/lib/tyto/program/publish.py
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#-------------------------
|
|
||||||
# Funny Stats Project
|
|
||||||
#-------------------------
|
|
||||||
# file lines : 294
|
|
||||||
# file comments : 50
|
|
||||||
# file functions: 6
|
|
||||||
# file program : 206
|
|
||||||
#--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
import os, sys, shutil, importlib, subprocess
|
|
||||||
from pathlib import Path
|
|
||||||
import logs, args, dom, db, wip, html, tyto, form, stats, rss, langs, check
|
|
||||||
|
|
||||||
|
|
||||||
#==============================#
|
|
||||||
# Manage action, get post db #
|
|
||||||
# check if publish can be done #
|
|
||||||
#------------------------------#
|
|
||||||
def manage(target):
|
|
||||||
dom.valid()
|
|
||||||
|
|
||||||
# Specific QUICK processes: check > wip > publish
|
|
||||||
if args.action == "quick-pub":
|
|
||||||
try: db.uri_file
|
|
||||||
except: logs.out("28", "%s + %s"%(args.action, args.target), True)
|
|
||||||
|
|
||||||
wip = subprocess.run(
|
|
||||||
[
|
|
||||||
'/usr/bin/tyto',
|
|
||||||
'force-wip',
|
|
||||||
target
|
|
||||||
],
|
|
||||||
)
|
|
||||||
importlib.reload(db)
|
|
||||||
check_to_publish('one')
|
|
||||||
publish_article()
|
|
||||||
rss.create_feed()
|
|
||||||
return
|
|
||||||
|
|
||||||
# Target is footer, sidebar, navbar, metas
|
|
||||||
# template: create/copy template/ files
|
|
||||||
# all: publish all wip article
|
|
||||||
#-----------------------------------------
|
|
||||||
elif target in args.pass_targets:
|
|
||||||
do = {
|
|
||||||
'updated' : publish_all,
|
|
||||||
'again' : publish_all,
|
|
||||||
'added' : publish_all,
|
|
||||||
'sidebar' : html.create_sidebar,
|
|
||||||
'navbar' : html.create_navbar,
|
|
||||||
'metas' : html.create_user_metas,
|
|
||||||
'footer' : html.create_user_footer,
|
|
||||||
'template' : publish_template,
|
|
||||||
'stats' : stats.manage
|
|
||||||
}
|
|
||||||
|
|
||||||
do[target]('www')
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
# Database must exists...
|
|
||||||
if not target: logs.out("5", '', True)
|
|
||||||
if not db.post: logs.out("1", db.uri_file, True)
|
|
||||||
if not db.exists: logs.out("25", db.uri_file, True)
|
|
||||||
|
|
||||||
# Publish in www server an article
|
|
||||||
check_to_publish('one')
|
|
||||||
|
|
||||||
# Article already published
|
|
||||||
if db.file_www:
|
|
||||||
logs.out("85", '%s > %s'%(db.date_chk, db.uri_file), False)
|
|
||||||
answer = form.asking(' ├ %s%s '%(
|
|
||||||
langs.site.publish_a, langs.site.q
|
|
||||||
), True)
|
|
||||||
|
|
||||||
# Publish
|
|
||||||
publish_article()
|
|
||||||
|
|
||||||
# Create new ATOM/RSS file
|
|
||||||
rss.create_feed()
|
|
||||||
|
|
||||||
|
|
||||||
#============================================#
|
|
||||||
# Option 'all' to publish again, based on DB #
|
|
||||||
#--------------------------------------------#
|
|
||||||
def publish_all(option):
|
|
||||||
tyto.show_multi_message('www', dom.srv_www)
|
|
||||||
form.asking(' ├ %s%s '%(langs.site.proceed, langs.site.q), True)
|
|
||||||
|
|
||||||
# Sort by newer articles (created by last check)
|
|
||||||
db_articles = sorted(Path(dom.articles_db_d).iterdir(),
|
|
||||||
key=os.path.getmtime
|
|
||||||
)
|
|
||||||
|
|
||||||
# Load domain configuration DB
|
|
||||||
option = args.target
|
|
||||||
found = False
|
|
||||||
for post_db in db_articles:
|
|
||||||
if not str(post_db).endswith('.config'): continue
|
|
||||||
|
|
||||||
# Load DB
|
|
||||||
exec(open(post_db).read(),globals())
|
|
||||||
args.target = short_src
|
|
||||||
importlib.reload(db)
|
|
||||||
|
|
||||||
if option == "again" and not db.www_again: continue
|
|
||||||
elif option == "added" and not db.www_added: continue
|
|
||||||
elif option == "updated" and not db.www_updated: continue
|
|
||||||
|
|
||||||
check_to_publish('all')
|
|
||||||
if err_pub:
|
|
||||||
continue
|
|
||||||
|
|
||||||
found = True
|
|
||||||
publish_article()
|
|
||||||
|
|
||||||
if not found:
|
|
||||||
logs.out("28", 'publish %s'%option, True)
|
|
||||||
|
|
||||||
# If found: create new ATOM/RSS file
|
|
||||||
rss.create_feed()
|
|
||||||
|
|
||||||
|
|
||||||
#==============================#
|
|
||||||
# Check if it can be published #
|
|
||||||
#------------------------------#
|
|
||||||
def check_to_publish(process):
|
|
||||||
global err_pub
|
|
||||||
err_pub = False
|
|
||||||
|
|
||||||
print(' │')
|
|
||||||
db.show_title()
|
|
||||||
|
|
||||||
# Article was not checked or changed
|
|
||||||
if db.no_chk:
|
|
||||||
logs.out("25", db.uri_file, False)
|
|
||||||
err_pub = 25
|
|
||||||
elif db.old_chk:
|
|
||||||
logs.out("9", db.uri_file, False)
|
|
||||||
err_pub = 9
|
|
||||||
|
|
||||||
# Article must exists in wip server
|
|
||||||
if db.no_wip or db.old_wip:
|
|
||||||
logs.out("30", db.uri_file, False)
|
|
||||||
err_pub = 30
|
|
||||||
elif not db.file_wip:
|
|
||||||
logs.out("1", db.post_wip, False)
|
|
||||||
err_pub = 1
|
|
||||||
|
|
||||||
if err_pub:
|
|
||||||
if process == 'all': return
|
|
||||||
elif process == 'one': sys.exit(err_pub)
|
|
||||||
|
|
||||||
|
|
||||||
#===============#
|
|
||||||
# Let's publish #
|
|
||||||
#---------------#
|
|
||||||
def publish_article():
|
|
||||||
# Copy wip page to www page
|
|
||||||
if os.makedirs('%s%s'%(dom.srv_www, db.direc_src), exist_ok=True):
|
|
||||||
logs.out("33", '%s%s'%(dom.srv_www, db.direc_src), False)
|
|
||||||
|
|
||||||
# Replace in DB hash_wip and date_wip
|
|
||||||
db_values = \
|
|
||||||
[
|
|
||||||
("date_www", '"%s"'%db.date_www, '"%s"'%tyto.nowdate()),
|
|
||||||
("hash_www", '"%s"'%db.hash_www, '"%s"'%db.hash_post),
|
|
||||||
("static_www", '%s'%db.static_www, '%s'%db.static_wip)
|
|
||||||
]
|
|
||||||
tyto.change_in_db(db.config, db_values)
|
|
||||||
|
|
||||||
# Copy needed files (Also create sub-folders)
|
|
||||||
tyto.files_to_srv('www')
|
|
||||||
|
|
||||||
# Replace publish HTML line
|
|
||||||
replace_lines_pub()
|
|
||||||
|
|
||||||
|
|
||||||
#=================================================#
|
|
||||||
# Replace line in article containing publish date #
|
|
||||||
#-------------------------------------------------#
|
|
||||||
def replace_lines_pub():
|
|
||||||
html.create_html_time_meta('publish')
|
|
||||||
|
|
||||||
in_pub = False
|
|
||||||
wip_html_post = open(db.post_wip, 'r').read()
|
|
||||||
www_html_post = wip_html_post
|
|
||||||
|
|
||||||
for line in wip_html_post.rsplit('\n'):
|
|
||||||
if line.startswith('<!--Tyto_Published-->'):
|
|
||||||
in_pub = True
|
|
||||||
time_wip_pub = line
|
|
||||||
continue
|
|
||||||
|
|
||||||
elif line.startswith('<!--/Tyto_Published-->'):
|
|
||||||
time_wip_pub = '%s\n%s'%(time_wip_pub, line)
|
|
||||||
in_pub = False
|
|
||||||
break
|
|
||||||
|
|
||||||
elif line.startswith('<!--Tyto_Meta-->'):
|
|
||||||
time_wip_meta = line
|
|
||||||
continue
|
|
||||||
|
|
||||||
if in_pub:
|
|
||||||
time_wip_pub = '%s\n%s'%(time_wip_pub, line)
|
|
||||||
|
|
||||||
# Update file with new time meta
|
|
||||||
try:
|
|
||||||
www_html_post = \
|
|
||||||
www_html_post.replace(time_wip_meta,
|
|
||||||
html.meta_pub
|
|
||||||
)
|
|
||||||
except:
|
|
||||||
logs.out("45", db.post_www, False)
|
|
||||||
|
|
||||||
# update file with new article time
|
|
||||||
try:
|
|
||||||
www_html_post = \
|
|
||||||
www_html_post.replace(time_wip_pub,
|
|
||||||
html.time_html_pub
|
|
||||||
)
|
|
||||||
except:
|
|
||||||
logs.out("46", db.post_www, False)
|
|
||||||
|
|
||||||
|
|
||||||
tyto.set_file(db.post_www, 'New', www_html_post)
|
|
||||||
|
|
||||||
|
|
||||||
#================================#
|
|
||||||
# Publish template in www server #
|
|
||||||
#--------------------------------#
|
|
||||||
def publish_template(option):
|
|
||||||
form.asking(' ├ %s%s > %s '%(
|
|
||||||
langs.site.uptpl, langs.site.q,
|
|
||||||
dom.srv_www_tpl_d
|
|
||||||
), True)
|
|
||||||
|
|
||||||
# Copy all file in wip server template, except "nofiles"
|
|
||||||
nofiles = (
|
|
||||||
'footer.html',
|
|
||||||
'metas.html',
|
|
||||||
'navbar.html',
|
|
||||||
'sidebar.html'
|
|
||||||
)
|
|
||||||
|
|
||||||
for item in os.listdir(dom.srv_wip_tpl_d):
|
|
||||||
if item.startswith(nofiles):
|
|
||||||
continue
|
|
||||||
|
|
||||||
item_src = '%s%s'%(dom.srv_wip_tpl_d, item)
|
|
||||||
item_dst = '%s%s'%(dom.srv_www_tpl_d, item)
|
|
||||||
if os.path.isdir(item_src):
|
|
||||||
shutil.copytree(item_src, item_dst, dirs_exist_ok=True)
|
|
||||||
logs.out("33", item_dst, False)
|
|
||||||
else:
|
|
||||||
shutil.copy2(item_src, item_dst)
|
|
||||||
logs.out("32", item_dst, False)
|
|
||||||
|
|
||||||
# Create new file from _configs/ files
|
|
||||||
if args.option == "--no-mods":
|
|
||||||
return
|
|
||||||
|
|
||||||
html.create_sidebar('pub')
|
|
||||||
html.create_navbar('pub')
|
|
||||||
html.create_user_metas('pub')
|
|
||||||
html.create_user_footer('pub')
|
|
||||||
|
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Tyto - Littérateur
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License
|
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# XMPP: echolib (im@echolib.re)
|
|
||||||
#
|
|
||||||
# Description: Create feed RSS/Atom
|
|
||||||
# File: /var/lib/tyto/program/rss.py
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#-------------------------
|
|
||||||
# Funny Stats Project
|
|
||||||
#-------------------------
|
|
||||||
# file lines : 129
|
|
||||||
# file comments : 28
|
|
||||||
# file functions: 1
|
|
||||||
# file program : 90
|
|
||||||
#--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
import logs, dom, db, tyto, langs
|
|
||||||
|
|
||||||
|
|
||||||
#============================#
|
|
||||||
# Create ATOM/RSS feed #
|
|
||||||
# only with publish argument #
|
|
||||||
#----------------------------#
|
|
||||||
def create_feed():
|
|
||||||
# Generic fedd Header
|
|
||||||
set_f = \
|
|
||||||
'<?xml version="1.0" encoding="utf-8"?>\n' + \
|
|
||||||
'<rss version="2.0">\n' + \
|
|
||||||
' <channel>\n' + \
|
|
||||||
' <title>%s - %s - Flux RSS 2.0</title>\n'%(
|
|
||||||
dom.title, dom.www_url
|
|
||||||
) + \
|
|
||||||
' <link>%s</link>\n'%dom.www_url + \
|
|
||||||
' <description>RSS 2.0 - %s (%s)</description>\n'%(
|
|
||||||
dom.title, dom.about
|
|
||||||
) + \
|
|
||||||
' <image>\n' + \
|
|
||||||
' <url>%s/%s</url>\n'%(dom.www_url, dom.logo) + \
|
|
||||||
' <title>logo %s</title>\n'%dom.title + \
|
|
||||||
' <link>%s</link>\n'%dom.www_url + \
|
|
||||||
' </image>\n' + \
|
|
||||||
' <language>%s</language>\n'%dom.lang_site + \
|
|
||||||
' <category>%s</category>\n'%dom.tags + \
|
|
||||||
' <lastBuildDate>%s</lastBuildDate>\n'%tyto.nowdate() + \
|
|
||||||
' <copyright>%s</copyright>\n'%dom.license + \
|
|
||||||
' <webMaster>%s</webMaster>\n'%dom.mail + \
|
|
||||||
' <generator>%s</generator>'%tyto.Tyto
|
|
||||||
|
|
||||||
# Sort by newer articles (created by last check)
|
|
||||||
db_articles = sorted(Path(dom.articles_db_d).iterdir(),
|
|
||||||
key=os.path.getmtime,
|
|
||||||
reverse=True
|
|
||||||
)
|
|
||||||
|
|
||||||
rss_item = False
|
|
||||||
nbr_item = 0
|
|
||||||
|
|
||||||
# Loop published articles. Get databases of articles
|
|
||||||
for post_db in db_articles:
|
|
||||||
if not str(post_db).endswith('.config'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Load DB
|
|
||||||
exec(open(post_db).read(),globals())
|
|
||||||
if not hash_www or hash_chk != hash_www:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# NoSitemap
|
|
||||||
if not db.sitemap:
|
|
||||||
continue
|
|
||||||
|
|
||||||
rss_item = True
|
|
||||||
nbr_item += 1
|
|
||||||
|
|
||||||
if nbr_item > dom.rss_items:
|
|
||||||
break
|
|
||||||
|
|
||||||
set_f = \
|
|
||||||
'%s\n'%set_f + \
|
|
||||||
'\n <item>\n' + \
|
|
||||||
' <title>%s</title>\n'%title + \
|
|
||||||
' <link>%s</link>\n'%http_www + \
|
|
||||||
' <guid>%s</guid>\n'%http_www + \
|
|
||||||
' <pubDate>%s</pubDate>\n'%date_www + \
|
|
||||||
' <description>%s</description>\n'%about + \
|
|
||||||
' <author>%s</author>\n'%author + \
|
|
||||||
' <image>\n' + \
|
|
||||||
' <url>%s</url>\n'%snpic + \
|
|
||||||
' <title>%s</title>\n'%(title) + \
|
|
||||||
' <link>%s</link>\n'%http_www + \
|
|
||||||
' </image>\n' + \
|
|
||||||
' <category>%s</category>\n'%tags + \
|
|
||||||
' </item>'
|
|
||||||
|
|
||||||
|
|
||||||
# Do nothing if no item
|
|
||||||
if not rss_item:
|
|
||||||
logs.out("28", '(ATOM/RSS)', False)
|
|
||||||
return
|
|
||||||
|
|
||||||
set_f = \
|
|
||||||
'%s\n'%set_f + \
|
|
||||||
' </channel>\n' + \
|
|
||||||
'</rss>'
|
|
||||||
|
|
||||||
print(' │\n ├─ %s'%langs.site.rss_c)
|
|
||||||
tyto.set_file(dom.www_rss_f, 'New', set_f)
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Tyto - Littérateur
|
||||||
|
|
||||||
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# XMPP: echolib (im@echolib.re)
|
||||||
|
#
|
||||||
|
# Description: When user wants to set something (mainly in domain)
|
||||||
|
# File: /var/lib/tyto/program/set.py
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-------------------------
|
||||||
|
# Funny Stats Project
|
||||||
|
#-------------------------
|
||||||
|
# file lines :
|
||||||
|
# file comments :
|
||||||
|
# file functions:
|
||||||
|
# file program :
|
||||||
|
#--------------------------
|
||||||
|
|
|
@ -1,216 +1,65 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Tyto - Littérateur
|
# Tyto - Littérateur
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License
|
# it under the terms of the GNU General Public License as published by
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# License, or of the License, or (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU Affero General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# XMPP: echolib (im@echolib.re)
|
# XMPP: echolib (im@echolib.re)
|
||||||
#
|
#
|
||||||
# Description: Manage show*/edit* arguments.
|
# Description: When user wants to see something
|
||||||
# Read or edit file from [target] argument
|
|
||||||
# File: /var/lib/tyto/program/show.py
|
# File: /var/lib/tyto/program/show.py
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
#-------------------------
|
#-------------------------
|
||||||
# Funny Stats Project
|
# Funny Stats Project
|
||||||
#-------------------------
|
#-------------------------
|
||||||
# file lines : 216
|
# file lines :
|
||||||
# file comments : 39
|
# file comments :
|
||||||
# file functions: 3
|
# file functions:
|
||||||
# file program : 156
|
# file program :
|
||||||
#--------------------------
|
#--------------------------
|
||||||
|
|
||||||
|
import os
|
||||||
import os, sys, importlib, subprocess
|
import domain, debug
|
||||||
import args, logs, langs, dom, db, form, tyto, check, html, stats
|
|
||||||
|
|
||||||
|
|
||||||
#========================#
|
#====================================#
|
||||||
# Read lines from a file #
|
# Manage arguments from command line #
|
||||||
# alone: True/False #
|
# Specific to action "show" #
|
||||||
#------------------------#
|
#------------------------------------#
|
||||||
def read_lines(f, alone):
|
def manage(action, target):
|
||||||
if not f: return
|
do = {
|
||||||
if not tyto.exists(f): logs.out("1", f, True)
|
"domains": all_domains,
|
||||||
|
}
|
||||||
|
|
||||||
datas = open(f).read()
|
do[target]()
|
||||||
|
|
||||||
# Align content line, after line number
|
|
||||||
ln_datas = len(datas.splitlines()) + 1
|
|
||||||
sp_max = len(str(ln_datas))
|
|
||||||
|
|
||||||
print(' ├', f)
|
|
||||||
print(' ├─%s─┐'%(sp_max * '─'))
|
|
||||||
for ln, line in enumerate(datas.rsplit('\n'), 1):
|
|
||||||
sp = sp_max - len(str(ln))
|
|
||||||
print(' │%s %s │ %s'%(int(sp) * " ", ln, line))
|
|
||||||
|
|
||||||
# Ends for show. False should be for form
|
|
||||||
if alone: decor = '└'
|
|
||||||
else: decor = '├'
|
|
||||||
print(' %s─%s─┘'%(decor, sp_max * '─'))
|
|
||||||
|
|
||||||
if not f == dom.config: dom.valid()
|
|
||||||
|
|
||||||
|
|
||||||
#======================#
|
#============================#
|
||||||
# From command line: #
|
# List all registred domains #
|
||||||
# Show or edit file #
|
#----------------------------#
|
||||||
# final html, db, src #
|
def all_domains():
|
||||||
#----------------------#
|
domain.ult_dlf_load()
|
||||||
def manage(target):
|
|
||||||
if not dom.exists: logs.out("10", '', True)
|
|
||||||
dom.valid()
|
|
||||||
|
|
||||||
actions_read = ('show', 'show-about', 'show-db', 'show-wip', 'show-www')
|
|
||||||
actions_edit = ('edit', 'edit-about', 'edit-db', 'edit-wip', 'edit-www')
|
|
||||||
post_src = post_db = post_wip = post_www = False
|
|
||||||
|
|
||||||
# Set file from post DB when target is an article
|
|
||||||
#------------------------------------------------
|
|
||||||
try: post_src = db.uri_file
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
if post_src:
|
|
||||||
target = "post"
|
|
||||||
try: post_db = db.config
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
try: post_wip = db.post_wip
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
try: post_www = db.post_www
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Convert command action to do[]
|
|
||||||
# as edit* &nd show* [action] have same target file
|
|
||||||
actions = \
|
|
||||||
{
|
|
||||||
"show" : 'src',
|
|
||||||
"edit" : 'src',
|
|
||||||
"post" : 'src',
|
|
||||||
"preview" : 'wip',
|
|
||||||
"show-db" : 'db',
|
|
||||||
"edit-db" : 'db',
|
|
||||||
"show-wip" : 'wip',
|
|
||||||
"edit-wip" : 'wip',
|
|
||||||
"show-www" : 'www',
|
|
||||||
"edit-www" : 'www'
|
|
||||||
}
|
|
||||||
action = actions[args.action]
|
|
||||||
|
|
||||||
# Set target file from "new" [action]
|
|
||||||
do = \
|
|
||||||
{
|
|
||||||
'src' : {
|
|
||||||
"domain" : dom.config,
|
|
||||||
"footer" : dom.footer_f,
|
|
||||||
"metas" : dom.metas_f,
|
|
||||||
"navbar" : dom.navbar_f,
|
|
||||||
"sidebar" : dom.sidebar_f,
|
|
||||||
"post" : post_src
|
|
||||||
},
|
|
||||||
'db' : {
|
|
||||||
"domain" : dom.config,
|
|
||||||
"footer" : dom.footer_f,
|
|
||||||
"metas" : dom.metas_f,
|
|
||||||
"navbar" : dom.navbar_f,
|
|
||||||
"sidebar" : dom.sidebar_f,
|
|
||||||
"post" : post_db
|
|
||||||
},
|
|
||||||
'wip' : {
|
|
||||||
"domain" : dom.config,
|
|
||||||
"footer" : dom.wip_footer_f,
|
|
||||||
"metas" : dom.wip_metas_f,
|
|
||||||
"navbar" : dom.wip_navbar_f,
|
|
||||||
"sidebar" : dom.wip_sidebar_f,
|
|
||||||
"post" : post_wip,
|
|
||||||
"sitemap" : '%ssitemap.html'%dom.srv_wip,
|
|
||||||
"stats" : dom.wip_stats_f,
|
|
||||||
},
|
|
||||||
'www' : {
|
|
||||||
"domain" : dom.config,
|
|
||||||
"footer" : dom.www_footer_f,
|
|
||||||
"metas" : dom.www_metas_f,
|
|
||||||
"navbar" : dom.www_navbar_f,
|
|
||||||
"sidebar" : dom.www_sidebar_f,
|
|
||||||
"post" : post_www,
|
|
||||||
"stats" : dom.www_stats_f,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
# Read or edit file, according to legacy args.action
|
|
||||||
file = do[action][target]
|
|
||||||
if not file:
|
|
||||||
logs.out("28", '%s + %s'%(args.action, args.target), True)
|
|
||||||
|
|
||||||
if not file or not tyto.exists(file):
|
|
||||||
logs.out("1", file, True)
|
|
||||||
|
|
||||||
# Except for show-about > Show post DB
|
|
||||||
if args.action == "preview":
|
|
||||||
preview_wip(file)
|
|
||||||
return
|
|
||||||
|
|
||||||
elif args.action in actions_read:
|
|
||||||
read_lines(file, True)
|
|
||||||
|
|
||||||
elif args.action in actions_edit:
|
|
||||||
curr_hash = tyto.get_filesum(file, True)
|
|
||||||
tyto.edit_file(file)
|
|
||||||
|
|
||||||
|
|
||||||
# If edit article and hash changed, ask to check
|
|
||||||
if args.action == "edit":
|
|
||||||
new_hash = tyto.get_filesum(file, True)
|
|
||||||
|
|
||||||
if curr_hash == new_hash: return
|
|
||||||
|
|
||||||
# Launch process for some changed file
|
|
||||||
#-------------------------------------
|
|
||||||
if file == post_src:
|
|
||||||
# Reload post DB (if edited article, and check it if ask "y")
|
|
||||||
importlib.reload(db)
|
|
||||||
check = subprocess.run(
|
|
||||||
[
|
|
||||||
'/usr/bin/tyto',
|
|
||||||
'check',
|
|
||||||
args.target
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
elif file == dom.sidebar_f: html.create_sidebar('wip')
|
|
||||||
elif file == dom.navbar_f: html.create_navbar('wip')
|
|
||||||
elif file == dom.metas_f: html.create_user_metas('wip')
|
|
||||||
|
|
||||||
|
|
||||||
#=====================================#
|
|
||||||
# Preview in browser wip page #
|
|
||||||
# Ensure xdg-open (useless in server) #
|
|
||||||
#-------------------------------------#
|
|
||||||
def preview_wip(file):
|
|
||||||
try:
|
try:
|
||||||
xdg = subprocess.run(
|
c = 0
|
||||||
[
|
for key, value in domain.ult_dlf.items("DOMAINS"):
|
||||||
'/usr/bin/xdg-open',
|
if key: c += 1
|
||||||
file,
|
print(": %s > %s"%(key,value))
|
||||||
],
|
print("|\n; total =",c)
|
||||||
)
|
|
||||||
except:
|
except:
|
||||||
logs.out("28", "/usr/bin/xdg-open %s"%file, True)
|
debug.out(104, "False", domain.ult_dlf_uri, True, 1, False)
|
||||||
|
|
||||||
|
|
|
@ -1,226 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Tyto - Littérateur
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License
|
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# XMPP: echolib (im@echolib.re)
|
|
||||||
#
|
|
||||||
# Description: Create total statistics file for www or wip
|
|
||||||
# File: /var/lib/tyto/program/stats.py
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#-------------------------
|
|
||||||
# Funny Stats Project
|
|
||||||
#-------------------------
|
|
||||||
# file lines : 226
|
|
||||||
# file comments : 38
|
|
||||||
# file functions: 4
|
|
||||||
# file program : 166
|
|
||||||
#--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
import os, importlib
|
|
||||||
import args, dom, logs, form, tyto, show, langs
|
|
||||||
|
|
||||||
|
|
||||||
sti_articles = 0
|
|
||||||
|
|
||||||
#=======================#
|
|
||||||
# Manage "stats" option #
|
|
||||||
#-----------------------#
|
|
||||||
def manage(process):
|
|
||||||
dom.valid()
|
|
||||||
|
|
||||||
global file_uri, domain_srv
|
|
||||||
|
|
||||||
if process == 'wip':
|
|
||||||
file_uri = dom.wip_stats_f
|
|
||||||
domain_srv = dom.wip_url
|
|
||||||
elif process == 'www':
|
|
||||||
file_uri = dom.www_stats_f
|
|
||||||
domain_srv = dom.www_url
|
|
||||||
|
|
||||||
loop_articles(process)
|
|
||||||
|
|
||||||
|
|
||||||
#==========================#
|
|
||||||
# Check databases' article #
|
|
||||||
#--------------------------#
|
|
||||||
def loop_articles(process):
|
|
||||||
global sti_articles
|
|
||||||
|
|
||||||
# Get databases of articles
|
|
||||||
for db in os.listdir(dom.articles_db_d):
|
|
||||||
if not db.endswith('.config'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Load DB
|
|
||||||
db = '%s%s'%(dom.articles_db_d, db)
|
|
||||||
exec(open(db).read(),globals())
|
|
||||||
|
|
||||||
# Check hash status (wip/www)
|
|
||||||
hash_srv = ''
|
|
||||||
if process == 'wip': hash_srv = hash_wip
|
|
||||||
elif process == 'www': hash_srv = hash_www
|
|
||||||
|
|
||||||
# - Now generic for wip and www
|
|
||||||
# - Article has changed and could have different stats
|
|
||||||
if not hash_srv or \
|
|
||||||
hash_srv != hash_chk:
|
|
||||||
continue
|
|
||||||
|
|
||||||
sti_articles += 1
|
|
||||||
if sti_articles == 1: count_stats(False)
|
|
||||||
else: count_stats(True)
|
|
||||||
|
|
||||||
# Create file if article
|
|
||||||
if sti_articles > 0: create_stats_file(file_uri)
|
|
||||||
else: logs.out("28", '%s stats'%process, True)
|
|
||||||
|
|
||||||
|
|
||||||
#===============================#
|
|
||||||
# False: Set First statistics #
|
|
||||||
# True: Count total statistics #
|
|
||||||
#-------------------------------#
|
|
||||||
def count_stats(add):
|
|
||||||
# Set
|
|
||||||
if not add:
|
|
||||||
global stats, authors, author_names
|
|
||||||
|
|
||||||
# Specific for Authors (not in database stats)
|
|
||||||
author_names = author.replace(' ', '').split(",")
|
|
||||||
authors = 0
|
|
||||||
|
|
||||||
stats = { \
|
|
||||||
"sti_uniq_anchors" : uniq_anchors,
|
|
||||||
"sti_uniq_abbrs" : uniq_abbrs,
|
|
||||||
"sti_uniq_links" : uniq_links,
|
|
||||||
"sti_uniq_images" : uniq_images,
|
|
||||||
"sti_uniq_files" : uniq_files,
|
|
||||||
"sti_uniq_codes" : uniq_codes,
|
|
||||||
"sti_uniq_raws" : uniq_raws,
|
|
||||||
"sti_comments" : comments,
|
|
||||||
"sti_tags" : tags,
|
|
||||||
"sti_lines" : lines,
|
|
||||||
"sti_words" : words,
|
|
||||||
"sti_titles" : titles,
|
|
||||||
"sti_paragraphs" : paragraphs,
|
|
||||||
"sti_links" : links,
|
|
||||||
"sti_images" : images,
|
|
||||||
"sti_anchors" : anchors,
|
|
||||||
"sti_abbrs" : abbrs,
|
|
||||||
"sti_strongs" : strongs,
|
|
||||||
"sti_bolds" : bolds,
|
|
||||||
"sti_emphasis" : emphasis,
|
|
||||||
"sti_italics" : italics,
|
|
||||||
"sti_dels" : dels,
|
|
||||||
"sti_underlines" : underlines,
|
|
||||||
"sti_cites" : cites,
|
|
||||||
"sti_customs" : customs,
|
|
||||||
"sti_icodes" : icodes,
|
|
||||||
"sti_bcodes" : bcodes,
|
|
||||||
"sti_quotes" : quotes,
|
|
||||||
"sti_lists" : lists,
|
|
||||||
"sti_files" : files,
|
|
||||||
"sti_raws" : raws,
|
|
||||||
"sti_codes" : codes,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Count
|
|
||||||
else:
|
|
||||||
# Authors are not set in database stats
|
|
||||||
new_authors = author.replace(' ', '').split(",")
|
|
||||||
|
|
||||||
# Do not count author if known
|
|
||||||
for name in new_authors:
|
|
||||||
if name in author_names:
|
|
||||||
continue
|
|
||||||
|
|
||||||
author_names = author_names + [name]
|
|
||||||
|
|
||||||
# From database stats
|
|
||||||
for i in stats:
|
|
||||||
stat_db = i.rsplit("sti_")[1]
|
|
||||||
stats[i] = stats[i] + eval(stat_db)
|
|
||||||
|
|
||||||
|
|
||||||
#============================#
|
|
||||||
# Create stat file in server #
|
|
||||||
#----------------------------#
|
|
||||||
def create_stats_file(file_uri):
|
|
||||||
# Count authors
|
|
||||||
authors = len(author_names)
|
|
||||||
|
|
||||||
sti = \
|
|
||||||
'# Statistics file created by %s\n'%tyto.Tyto + \
|
|
||||||
'# Website: %s\n'%domain_srv + \
|
|
||||||
'# File: %s\n'%file_uri + \
|
|
||||||
'# Generated: %s\n'%tyto.nowdate() + \
|
|
||||||
'\n' + \
|
|
||||||
'# Uniq statistics from articles headers\n' + \
|
|
||||||
'articles = %d\n'%int(sti_articles) + \
|
|
||||||
'uniq_authors = %d\n'%int(authors) + \
|
|
||||||
'uniq_anchors = %d\n'%stats["sti_uniq_anchors"] + \
|
|
||||||
'uniq_abbrs = %d\n'%stats["sti_uniq_abbrs"] + \
|
|
||||||
'uniq_links = %d\n'%stats["sti_uniq_links"] + \
|
|
||||||
'uniq_images = %d\n'%stats["sti_uniq_images"] + \
|
|
||||||
'uniq_files = %d\n'%stats["sti_uniq_files"] + \
|
|
||||||
'uniq_codes = %d\n'%stats["sti_uniq_codes"] + \
|
|
||||||
'uniq_raws = %d\n'%stats["sti_uniq_raws"] + \
|
|
||||||
'\n' + \
|
|
||||||
'# Statistics from articles contents\n' + \
|
|
||||||
'comments = %d\n'%stats["sti_comments"] + \
|
|
||||||
'tags = %d\n'%stats["sti_tags"] + \
|
|
||||||
'lines = %d\n'%stats["sti_lines"] + \
|
|
||||||
'words = %d\n'%stats["sti_words"] + \
|
|
||||||
'titles = %d\n'%stats["sti_titles"] + \
|
|
||||||
'paragraphs = %d\n'%stats["sti_paragraphs"] + \
|
|
||||||
'links = %d\n'%stats["sti_links"] + \
|
|
||||||
'images = %d\n'%stats["sti_images"] + \
|
|
||||||
'anchors = %d\n'%stats["sti_anchors"] + \
|
|
||||||
'abbrs = %d\n'%stats["sti_abbrs"] + \
|
|
||||||
'strongs = %d\n'%stats["sti_strongs"] + \
|
|
||||||
'bolds = %d\n'%stats["sti_bolds"] + \
|
|
||||||
'emphasis = %d\n'%stats["sti_emphasis"] + \
|
|
||||||
'italics = %d\n'%stats["sti_italics"] + \
|
|
||||||
'dels = %d\n'%stats["sti_dels"] + \
|
|
||||||
'underlines = %d\n'%stats["sti_underlines"] + \
|
|
||||||
'cites = %d\n'%stats["sti_cites"] + \
|
|
||||||
'customs = %d\n'%stats["sti_customs"] + \
|
|
||||||
'icodes = %d\n'%stats["sti_icodes"] + \
|
|
||||||
'bcodes = %d\n'%stats["sti_bcodes"] + \
|
|
||||||
'quotes = %d\n'%stats["sti_quotes"] + \
|
|
||||||
'lists = %d\n'%stats["sti_lists"] + \
|
|
||||||
'\n' + \
|
|
||||||
'# Included files in articles contents\n' + \
|
|
||||||
'files = %d\n'%stats["sti_files"] + \
|
|
||||||
'codes = %d\n'%stats["sti_codes"] + \
|
|
||||||
'raws = %d\n'%stats["sti_raws"]
|
|
||||||
|
|
||||||
|
|
||||||
tyto.set_file(file_uri, 'New', sti)
|
|
||||||
try:
|
|
||||||
print(' └', langs.site.stats_f%(
|
|
||||||
sti_articles, stats["sti_words"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
except:
|
|
||||||
print(' └ Articles = %s ; Words = %s'%(
|
|
||||||
sti_articles, stats["sti_words"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,241 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Tyto - Littérateur
|
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License
|
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# XMPP: echolib (im@echolib.re)
|
|
||||||
#
|
|
||||||
# Description: Show statuses for commands, domain, article
|
|
||||||
# File: /var/lib/tyto/program/status.py
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
|
|
||||||
#-------------------------
|
|
||||||
# Funny Stats Project
|
|
||||||
#-------------------------
|
|
||||||
# file lines : 241
|
|
||||||
# file comments : 51
|
|
||||||
# file functions: 3
|
|
||||||
# file program : 170
|
|
||||||
#--------------------------
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import args, dom, logs
|
|
||||||
|
|
||||||
|
|
||||||
#=====================#
|
|
||||||
# Check domain status #
|
|
||||||
#---------------------#
|
|
||||||
def domain():
|
|
||||||
if dom.hole:
|
|
||||||
logs.out("13", '', True)
|
|
||||||
|
|
||||||
# Only condition to not check domain status here
|
|
||||||
if args.action == 'new' and \
|
|
||||||
args.target == "domain":
|
|
||||||
return
|
|
||||||
|
|
||||||
# As subprocesses, avoid show domain status each time
|
|
||||||
if args.action in args.quicks:
|
|
||||||
return
|
|
||||||
|
|
||||||
# [action] not in list
|
|
||||||
if args.act_err:
|
|
||||||
logs.out("11", args.action, True)
|
|
||||||
|
|
||||||
# No domain found
|
|
||||||
if not dom.exists:
|
|
||||||
logs.out("10", '', True)
|
|
||||||
|
|
||||||
# Domain id corrupted
|
|
||||||
if dom.corrupt:
|
|
||||||
logs.out("39", dom.shortname, True)
|
|
||||||
|
|
||||||
# Domain is incomplete
|
|
||||||
if dom.incomplete:
|
|
||||||
logs.out("41", dom.shortname, False)
|
|
||||||
# Show unused values
|
|
||||||
for err_val in dom.err_val:
|
|
||||||
logs.out("16", err_val, True)
|
|
||||||
|
|
||||||
# Domain not activated
|
|
||||||
if not dom.active:
|
|
||||||
logs.out("40", dom.shortname, True)
|
|
||||||
|
|
||||||
# Domain is activated
|
|
||||||
if dom.active:
|
|
||||||
logs.out("42", dom.shortname, False)
|
|
||||||
|
|
||||||
|
|
||||||
# No backward in [target]
|
|
||||||
if "../" in args.target:
|
|
||||||
logs.out("11", '"../"', True)
|
|
||||||
|
|
||||||
|
|
||||||
#===========================#
|
|
||||||
# Create unused directories #
|
|
||||||
#---------------------------#
|
|
||||||
import tyto
|
|
||||||
|
|
||||||
srv_show_wip = srv_show_www = local_show = dom_err = False
|
|
||||||
for value in dom.dom_values:
|
|
||||||
set_value = eval(str('dom.%s'%value))
|
|
||||||
|
|
||||||
# wip directories
|
|
||||||
if value.endswith('_d'):
|
|
||||||
if value.startswith("srv_wip"):
|
|
||||||
if not tyto.exists(set_value):
|
|
||||||
if not srv_show_wip:
|
|
||||||
print(' │\n │ [wip]')
|
|
||||||
srv_show_wip = True
|
|
||||||
try:
|
|
||||||
os.makedirs(set_value, exist_ok=True)
|
|
||||||
logs.out("33", set_value, False)
|
|
||||||
except:
|
|
||||||
logs.out("1", set_value, False)
|
|
||||||
dom_err = True
|
|
||||||
|
|
||||||
# www directories
|
|
||||||
elif value.startswith("srv_www"):
|
|
||||||
if not tyto.exists(set_value):
|
|
||||||
if not srv_show_www:
|
|
||||||
print(' │\n │ [www]')
|
|
||||||
srv_show_www = True
|
|
||||||
try:
|
|
||||||
os.makedirs(set_value, exist_ok=True)
|
|
||||||
logs.out("33", set_value, False)
|
|
||||||
except:
|
|
||||||
logs.out("1", set_value, False)
|
|
||||||
dom_err = True
|
|
||||||
|
|
||||||
# local directories
|
|
||||||
else:
|
|
||||||
if not tyto.exists(set_value):
|
|
||||||
if not local_show:
|
|
||||||
print(' │\n │ [local]')
|
|
||||||
local_show = True
|
|
||||||
try:
|
|
||||||
os.makedirs(set_value, exist_ok=True)
|
|
||||||
logs.out("33", set_value, False)
|
|
||||||
except:
|
|
||||||
logs.out("1", set_value, False)
|
|
||||||
dom_err = True
|
|
||||||
|
|
||||||
|
|
||||||
# Create missing modules files
|
|
||||||
import html
|
|
||||||
|
|
||||||
if not tyto.exists(dom.metas_f) or \
|
|
||||||
not tyto.exists(dom.wip_metas_f):
|
|
||||||
html.create_user_metas('new')
|
|
||||||
|
|
||||||
if not tyto.exists(dom.navbar_f) or \
|
|
||||||
not tyto.exists(dom.wip_navbar_f):
|
|
||||||
html.create_navbar('new')
|
|
||||||
|
|
||||||
if not tyto.exists(dom.sidebar_f) or \
|
|
||||||
not tyto.exists(dom.wip_sidebar_f):
|
|
||||||
html.create_sidebar('new')
|
|
||||||
|
|
||||||
if not tyto.exists(dom.footer_f) or \
|
|
||||||
not tyto.exists(dom.wip_footer_f):
|
|
||||||
html.create_user_footer('new')
|
|
||||||
|
|
||||||
|
|
||||||
#==============================#
|
|
||||||
# On demand with status action #
|
|
||||||
#------------------------------#
|
|
||||||
def check(target):
|
|
||||||
import db
|
|
||||||
|
|
||||||
# target needed
|
|
||||||
if not target:
|
|
||||||
logs.out("5", '[target]', True)
|
|
||||||
|
|
||||||
# Domain statuses
|
|
||||||
elif target == "domain":
|
|
||||||
# Check unused files in servers
|
|
||||||
logs.out("60", '', False)
|
|
||||||
check_domain_files("wip")
|
|
||||||
check_domain_files("www")
|
|
||||||
return
|
|
||||||
|
|
||||||
# target is an article
|
|
||||||
# Unused file
|
|
||||||
elif not db.post:
|
|
||||||
logs.out("1", db.uri_file, True)
|
|
||||||
|
|
||||||
# Article has DB
|
|
||||||
elif db.exists:
|
|
||||||
# Article datas
|
|
||||||
print(' │\n ├ [%s] > %s'%(db.title, db.uri_file))
|
|
||||||
|
|
||||||
# chk
|
|
||||||
if db.old_chk: logs.out("94", db.uri_file, False)
|
|
||||||
else: logs.out("20", db.uri_file, False)
|
|
||||||
|
|
||||||
# wip
|
|
||||||
print(' │ [wip]')
|
|
||||||
if not db.file_wip:
|
|
||||||
logs.out("91", db.post_wip, False)
|
|
||||||
else:
|
|
||||||
logs.out("92", db.post_wip, False)
|
|
||||||
# wip static
|
|
||||||
if db.static_wip: logs.out("96", db.post_wip, False)
|
|
||||||
else: logs.out("97", db.post_wip, False)
|
|
||||||
if db.no_wip: logs.out("98", db.post_wip, False)
|
|
||||||
elif db.old_wip: logs.out("99", db.post_wip, False)
|
|
||||||
else: logs.out("95", db.post_wip, False)
|
|
||||||
|
|
||||||
# www
|
|
||||||
print(' │ [www]')
|
|
||||||
if not db.file_www:
|
|
||||||
logs.out("91", db.post_www, False)
|
|
||||||
else:
|
|
||||||
logs.out("92", db.post_www, False)
|
|
||||||
# www static
|
|
||||||
if db.static_www: logs.out("96", db.post_wip, False)
|
|
||||||
else: logs.out("97", db.post_wip, False)
|
|
||||||
if db.no_www: logs.out("98", db.post_www, False)
|
|
||||||
elif db.old_www: logs.out("99", db.post_www, False)
|
|
||||||
else: logs.out("95", db.post_www, False)
|
|
||||||
return
|
|
||||||
|
|
||||||
# Article has NO DB
|
|
||||||
elif not db.exists:
|
|
||||||
logs.out("25", db.uri_file, True)
|
|
||||||
|
|
||||||
|
|
||||||
#=====================#
|
|
||||||
# Check servers files #
|
|
||||||
#---------------------#
|
|
||||||
def check_domain_files(srv):
|
|
||||||
import tyto
|
|
||||||
|
|
||||||
if srv == "www": template_files = dom.templates_files_www
|
|
||||||
elif srv == "wip": template_files = dom.templates_files_wip
|
|
||||||
else: return
|
|
||||||
|
|
||||||
dom_err = False
|
|
||||||
print(' │ [%s]'%srv)
|
|
||||||
for f in template_files:
|
|
||||||
if not tyto.exists(f):
|
|
||||||
dom_err = True
|
|
||||||
logs.out("1", f, False)
|
|
||||||
|
|
||||||
if not dom_err:
|
|
||||||
logs.out("28", 'tout va bien', False)
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Tyto - Littérateur
|
||||||
|
|
||||||
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# XMPP: echolib (im@echolib.re)
|
||||||
|
#
|
||||||
|
# Description: Tools used by Tyto - Littérateur
|
||||||
|
# File: /var/lib/tyto/program/tools.py
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-------------------------
|
||||||
|
# Funny Stats Project
|
||||||
|
#-------------------------
|
||||||
|
# file lines :
|
||||||
|
# file comments :
|
||||||
|
# file functions:
|
||||||
|
# file program :
|
||||||
|
#--------------------------
|
||||||
|
|
||||||
|
from hashlib import blake2b
|
||||||
|
import os, configparser
|
||||||
|
import debug
|
||||||
|
|
||||||
|
|
||||||
|
#========================#
|
||||||
|
# Return sum of src file #
|
||||||
|
# src: True = Content #
|
||||||
|
# False = URI #
|
||||||
|
#------------------------#
|
||||||
|
def get_filesum(path, src):
|
||||||
|
file_sum = blake2b(digest_size=4)
|
||||||
|
|
||||||
|
if src: file_sum.update(open(path, 'rb').read())
|
||||||
|
else: file_sum.update(path.encode())
|
||||||
|
|
||||||
|
return file_sum.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
#========================================#
|
||||||
|
# Check directory: exit if out and log #
|
||||||
|
# Mainly used to check domain server dir #
|
||||||
|
#----------------------------------------#
|
||||||
|
def dir_exists(dir_path, out):
|
||||||
|
exists = bool(os.path.exists(dir_path))
|
||||||
|
|
||||||
|
if not exists:
|
||||||
|
if out: debug.out(6, "False", dir_path, True, 2, True)
|
||||||
|
else: debug.out(6, "False", dir_path, True, 2, False)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
#============================#
|
||||||
|
# Create a new file and logs #
|
||||||
|
#----------------------------#
|
||||||
|
def create_file(file_path, contents):
|
||||||
|
up = bool(os.path.exists(file_path))
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(file_path, "w") as f:
|
||||||
|
f.write(contents)
|
||||||
|
except:
|
||||||
|
# Exit at error
|
||||||
|
debug.out(7, "False", file_path, True, 2, True)
|
||||||
|
|
||||||
|
if up: debug.out(207, file_path, False, 0, False)
|
||||||
|
else: debug.out(206, file_path, False, 0, False)
|
||||||
|
|
||||||
|
|
||||||
|
#===========================================#
|
||||||
|
# Update ini file, replacing existing value #
|
||||||
|
#-------------------------------------------#
|
||||||
|
def update_ini_file(file_path, section, key, val):
|
||||||
|
# Exit if no file
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
debug.out(5, "False", file_path, True, 2, True)
|
||||||
|
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(file_path)
|
||||||
|
config.set(section, key, val)
|
||||||
|
|
||||||
|
with open(file_path, "w") as f:
|
||||||
|
config.write(f)
|
||||||
|
|
||||||
|
|
||||||
|
#====================#
|
||||||
|
# Create directories #
|
||||||
|
#--------------------#
|
||||||
|
def create_dirs(path):
|
||||||
|
try:
|
||||||
|
if not os.path.exists(path):
|
||||||
|
os.makedirs(path, exist_ok=True)
|
||||||
|
debug.out(203, "True", path, False, 0, False)
|
||||||
|
except:
|
||||||
|
# Exit if not created
|
||||||
|
debug.out(5, "False", path, True, 2, True)
|
||||||
|
|
|
@ -1,725 +1,179 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Tyto - Littérateur
|
# Tyto - Littérateur
|
||||||
#
|
|
||||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU Affero General Public License
|
# it under the terms of the GNU General Public License as published by
|
||||||
# as published by the Free Software Foundation, either version 3 of the
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
# License, or of the License, or (at your option) any later version.
|
# (at your option) any later version.
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
# This program is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU Affero General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
# XMPP: echolib (im@echolib.re)
|
# XMPP: echolib (im@echolib.re)
|
||||||
#
|
#
|
||||||
# Description: Tools and some seetings.
|
# Description: Templates, settings, values
|
||||||
# File: /var/lib/tyto/program/tyto.py
|
# File: /var/lib/tyto/program/tyto.py
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
#-------------------------
|
#
|
||||||
# Funny Stats Project
|
# Arguments in command line #
|
||||||
#-------------------------
|
#
|
||||||
# file lines : 725
|
actions = (
|
||||||
# file comments : 121
|
"check", "wip", "publish",
|
||||||
# file functions: 14
|
"new",
|
||||||
# file program : 522
|
"set",
|
||||||
#--------------------------
|
"show",
|
||||||
|
)
|
||||||
|
|
||||||
|
targets = (
|
||||||
|
"domain",
|
||||||
|
"domains",
|
||||||
|
"title", "date", "about", "mail", "tags", "lang", "server",
|
||||||
|
)
|
||||||
|
|
||||||
|
force_options = ("--force", "-F")
|
||||||
|
debug_options = ("--debug", "-D")
|
||||||
|
debug_errors = ('--errors', "-E")
|
||||||
|
|
||||||
|
|
||||||
import os, sys, re, subprocess, locale, base64, datetime, shutil
|
#
|
||||||
from hashlib import blake2b
|
#
|
||||||
import args, dom, logs, langs
|
#
|
||||||
|
full_name = "Tyto - Littérateur"
|
||||||
|
web_url = "https://tyto.echolib.re"
|
||||||
|
git_url = "https://git.a-lec.org/echolib/tyto-litterateur"
|
||||||
|
|
||||||
|
|
||||||
# :D
|
#===========================#
|
||||||
Tyto = 'Tyto - Littérateur'
|
# Templates #==================================================
|
||||||
Tytogit = 'https://git.a-lec.org/echolib/tyto-litterateur'
|
# Domain configuration file #
|
||||||
Tytoweb = 'https://tyto.echolib.re'
|
#---------------------------#
|
||||||
|
ini_domain = """[DOMAIN]
|
||||||
|
activated = no
|
||||||
|
name =
|
||||||
|
title =
|
||||||
|
date =
|
||||||
|
about =
|
||||||
|
tags =
|
||||||
|
mail =
|
||||||
|
license = gfdl-1.3
|
||||||
|
license_url = https://www.gnu.org/licenses/fdl-1.3.txt
|
||||||
|
legals_url =
|
||||||
|
terms_url =
|
||||||
|
statuses_url =
|
||||||
|
|
||||||
|
[WEBSITE]
|
||||||
|
www_url =
|
||||||
|
wip_url =
|
||||||
|
lang =
|
||||||
|
css = tyto
|
||||||
|
separator = |
|
||||||
|
article_code = yes
|
||||||
|
static = no
|
||||||
|
|
||||||
# Needed header tags
|
[WEBSITE_MODULES]
|
||||||
needed_header_tags = \
|
navbar = yes
|
||||||
(
|
sidebar_title =
|
||||||
'title',
|
sidebar_items = 6
|
||||||
'about',
|
sitemaps = yes
|
||||||
'author',
|
rss_items = 100
|
||||||
'tags',
|
|
||||||
'date'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Optional header tags
|
[TEMPLATE_FILENAMES]
|
||||||
opt_header_tags = \
|
favicon = favicon.png
|
||||||
(
|
logo = logo.png
|
||||||
'file',
|
styles = styles.css
|
||||||
'image',
|
rss = rss.xml
|
||||||
'link',
|
stats = stats.ini
|
||||||
'abbr',
|
|
||||||
'raw',
|
|
||||||
'code',
|
|
||||||
'snpic'
|
|
||||||
)
|
|
||||||
|
|
||||||
opt_tags_long_name = \
|
[USER_DIRS]
|
||||||
(
|
root =
|
||||||
'link',
|
articles =
|
||||||
'file'
|
images =
|
||||||
)
|
files =
|
||||||
|
modules =
|
||||||
|
database =
|
||||||
|
template =
|
||||||
|
|
||||||
opt_tags_check_uri = \
|
[USER_TEMPLATE_FILES]
|
||||||
(
|
logo =
|
||||||
'image',
|
favicon =
|
||||||
'file',
|
styles =
|
||||||
'raw',
|
|
||||||
'code'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set all tags used in article's header
|
[USER_MODULES_FILES]
|
||||||
headers = \
|
metas =
|
||||||
(
|
header =
|
||||||
'title:',
|
navbar =
|
||||||
'about:',
|
sidebar =
|
||||||
'author:',
|
footer =
|
||||||
'tags:',
|
|
||||||
'date:',
|
|
||||||
'link:',
|
|
||||||
'image:',
|
|
||||||
'file:',
|
|
||||||
'abbr:',
|
|
||||||
'code:',
|
|
||||||
'raw:',
|
|
||||||
'#',
|
|
||||||
'snpic:',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
[SERVER]
|
||||||
|
root = /var/www/
|
||||||
|
domain =
|
||||||
|
|
||||||
# Words Tags (paragraphs, lists, bold, strong...)
|
[WIP_DIRS]
|
||||||
# Used to check, and replace (wip) tags
|
root =
|
||||||
# ! As base64 is used, do NOT set marker: =_ _=
|
images =
|
||||||
# [5] = name for stats and log.
|
files =
|
||||||
#-------------------------------------------------------------
|
template =
|
||||||
icode_tags = \
|
|
||||||
(
|
|
||||||
'{_', '_}',
|
|
||||||
'<code class="icode">', '</code>',
|
|
||||||
'icodes',
|
|
||||||
'\\{_', '\\_}'
|
|
||||||
)
|
|
||||||
|
|
||||||
strong_tags = \
|
[WIP_FILES]
|
||||||
(
|
favicon =
|
||||||
'*_', '_*',
|
logo =
|
||||||
'<strong class="%s">'%dom.css, '</strong>',
|
styles =
|
||||||
'strongs',
|
rss =
|
||||||
'\\*_', '\\_*',
|
stats =
|
||||||
'-S1-', '-S2-'
|
metas =
|
||||||
)
|
header =
|
||||||
|
navbar =
|
||||||
|
sidebar =
|
||||||
|
footer =
|
||||||
|
|
||||||
bold_tags = \
|
[WWW_DIRS]
|
||||||
(
|
root =
|
||||||
'+_', '_+',
|
images =
|
||||||
'<b class="%s">'%dom.css, '</b>',
|
files =
|
||||||
'bolds',
|
template =
|
||||||
'\\+_', '\\_+',
|
|
||||||
'-B1-', '-B2-'
|
|
||||||
)
|
|
||||||
|
|
||||||
em_tags = \
|
[WWW_FILES]
|
||||||
(
|
favicon =
|
||||||
';_', '_;',
|
logo =
|
||||||
'<em class="%s">'%dom.css, '</em>',
|
styles =
|
||||||
'emphasis',
|
rss =
|
||||||
'\\;_', '\\_;',
|
stats =
|
||||||
'-EM1-', '-EM2-'
|
metas =
|
||||||
)
|
header =
|
||||||
|
navbar =
|
||||||
i_tags = \
|
sidebar =
|
||||||
(
|
footer =
|
||||||
':_', '_:',
|
|
||||||
'<i class="%s">'%dom.css, '</i>',
|
|
||||||
'italics',
|
|
||||||
'\\:_', '\\_:',
|
|
||||||
'-I1-', '-I2-'
|
|
||||||
)
|
|
||||||
|
|
||||||
u_tags = \
|
|
||||||
(
|
|
||||||
'._', '_.', '<u class="%s">'%dom.css,
|
|
||||||
'</u>',
|
|
||||||
'underlines',
|
|
||||||
'\\._', '\\_.',
|
|
||||||
'-U1-', '-U2-'
|
|
||||||
)
|
|
||||||
|
|
||||||
del_tags = \
|
|
||||||
(
|
|
||||||
'~_', '_~',
|
|
||||||
'<del class="%s">'%dom.css, '</del>',
|
|
||||||
'dels',
|
|
||||||
'\\~_', '\\_~',
|
|
||||||
'-DE1-', '-DE2-'
|
|
||||||
)
|
|
||||||
|
|
||||||
cite_tags = \
|
|
||||||
(
|
|
||||||
'[_', '_]',
|
|
||||||
'<cite class="%s">'%dom.css, '</cite>',
|
|
||||||
'cites',
|
|
||||||
'\\[_', '\\_]',
|
|
||||||
'-CI1-', '-CI2-'
|
|
||||||
)
|
|
||||||
|
|
||||||
custom1_tags = \
|
|
||||||
(
|
|
||||||
'%_', '_%',
|
|
||||||
'<span class="custom">', '</span>',
|
|
||||||
'customs',
|
|
||||||
'\\%_', '\\_%',
|
|
||||||
'-CU1-', '-CU2-'
|
|
||||||
)
|
|
||||||
|
|
||||||
markers_tags = \
|
|
||||||
[
|
|
||||||
strong_tags,
|
|
||||||
bold_tags,
|
|
||||||
em_tags,
|
|
||||||
i_tags,
|
|
||||||
u_tags,
|
|
||||||
del_tags,
|
|
||||||
cite_tags,
|
|
||||||
custom1_tags,
|
|
||||||
]
|
|
||||||
|
|
||||||
# At begining line, create block contents
|
|
||||||
block_tags = [
|
|
||||||
('((', '))', '<p class="%s">', '</p>', 'paragraphs'),
|
|
||||||
('[[', ']]', '[[', ']]', 'quotes'),
|
|
||||||
('{{', '}}', '{{', '}}', 'bcodes'),
|
|
||||||
('-(', '-)', '-(', '-)', 'lists'),
|
|
||||||
('<<', '>>', '<div class="%s">', '</div>', 'div'),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Anchor tags
|
|
||||||
anchor_tags = \
|
|
||||||
(
|
|
||||||
'>_', '_<',
|
|
||||||
'<a class="anchor_link" href="#%s">', '</a>',
|
|
||||||
'anchors'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Tags that do not need to be paired
|
|
||||||
#-----------------------------------
|
|
||||||
single_tags = [
|
|
||||||
('|', '<br class="%s">'), # New Line
|
|
||||||
('->', '<a class="anchor_target" id="%s"></a>'), # Anchors
|
|
||||||
]
|
|
||||||
|
|
||||||
# When counting words, do no count line starting with:
|
|
||||||
nolinewords = \
|
|
||||||
(
|
|
||||||
block_tags[0][0], block_tags[0][1], # paragraphs
|
|
||||||
block_tags[1][0], block_tags[1][1], # quotes
|
|
||||||
block_tags[2][0], block_tags[2][1], # bcodes
|
|
||||||
block_tags[3][0], block_tags[3][1], # lists
|
|
||||||
single_tags[0][0], single_tags[1][0], # New line, anchor
|
|
||||||
'_%s:'%opt_header_tags[1], '_%s:'%opt_header_tags[4], # _image:, _raw:
|
|
||||||
'_%s:'%opt_header_tags[5] # _code
|
|
||||||
)
|
|
||||||
|
|
||||||
# warning symbols (Check if paired)
|
|
||||||
#----------------------------------
|
|
||||||
tpl_tags = [
|
|
||||||
('(', ')'),
|
|
||||||
('[', ']'),
|
|
||||||
('{', '}'),
|
|
||||||
('«', '»'),
|
|
||||||
]
|
|
||||||
|
|
||||||
# When including HTML in article, check some paired tags
|
|
||||||
#-------------------------------------------------------
|
|
||||||
leg_html_tags = [
|
|
||||||
('<!--', '-->'),
|
|
||||||
('<div', '</div>'),
|
|
||||||
('<ul', '</ul>'),
|
|
||||||
('<li', '</li>'),
|
|
||||||
('<p', '</p>'),
|
|
||||||
('<span','</span>'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# Markers for lists, to check in list content
|
|
||||||
#--------------------------------------------
|
|
||||||
markers_lists = ('+', '=', ' ', '#')
|
|
||||||
|
|
||||||
# Tags used for titles
|
|
||||||
#---------------------
|
|
||||||
titles_user = ('#1', '#2', '#3', '#4', '#5')
|
|
||||||
titles_html = ('<h1', '<h2', '<h3', '<h4', '<h5', '<h6')
|
|
||||||
titles_tags = [
|
|
||||||
("", "",),
|
|
||||||
('#1 ', '<h2 class="title_2">%s</h2>'),
|
|
||||||
('#2 ', '<h3 class="title_3">%s</h3>'),
|
|
||||||
('#3 ', '<h4 class="title_5">%s</h4>'),
|
|
||||||
('#4 ', '<h5 class="title_6">%s</h5>'),
|
|
||||||
('#5 ', '<h6 class="title_6">%s</h6>')
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
# Tags for quote
|
|
||||||
quote_tags = [
|
|
||||||
('_cite:', 'author'),
|
|
||||||
('_date:', 'date'),
|
|
||||||
('_link:', 'link'),
|
|
||||||
('_book:', 'book'),
|
|
||||||
('_lang:', 'lang')
|
|
||||||
]
|
|
||||||
|
|
||||||
# Tags to check in header in content _TAG
|
|
||||||
head_tags = ("image:", "raw:", "code;")
|
|
||||||
|
|
||||||
# Valid characters for some datas
|
|
||||||
chrs_invalid = \
|
|
||||||
set('{}[]_()+*=/:%~´')
|
|
||||||
|
|
||||||
|
|
||||||
new_article = """%s
|
|
||||||
# Tyto - Litterateur (tyto new %s)
|
|
||||||
|
|
||||||
title:
|
|
||||||
about:
|
|
||||||
author: %s
|
|
||||||
tags:
|
|
||||||
date: %s
|
|
||||||
|
|
||||||
#abbr: TYTO
|
|
||||||
Le générateur de sites web Libre
|
|
||||||
Tyto - Littérateur
|
|
||||||
|
|
||||||
# Use this image for social networks
|
|
||||||
#snpic: Pic-1
|
|
||||||
#image: Pic-1
|
|
||||||
URI
|
|
||||||
Texte-alternatif
|
|
||||||
|
|
||||||
#link: lien 1
|
|
||||||
URI/URL
|
|
||||||
Text-alternatif
|
|
||||||
|
|
||||||
-----
|
|
||||||
#_image:Pic-1 c=title_class
|
|
||||||
|
|
||||||
#1
|
|
||||||
((
|
|
||||||
|
|
||||||
))
|
|
||||||
|
|
||||||
|
[TYTO]
|
||||||
|
domain_hash =
|
||||||
|
domain_conf =
|
||||||
|
domain_user =
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Stats for icodes, bcodes, quotes
|
# Template file configuration for each a created domain
|
||||||
nbr_icodes = 0
|
|
||||||
|
|
||||||
|
|
||||||
#=======#
|
|
||||||
# TOOLS #
|
|
||||||
#=======#--------------------------------------------------------------
|
|
||||||
#
|
#
|
||||||
# Return True if file exists
|
ini_domain_user = """[DOMAIN]
|
||||||
#
|
name =
|
||||||
def exists(uri):
|
hash =
|
||||||
if os.path.exists(uri): return(True)
|
root =
|
||||||
else: return(False)
|
conf =
|
||||||
|
|
||||||
|
[SERVER]
|
||||||
|
root =
|
||||||
|
"""
|
||||||
|
|
||||||
#========================================#
|
ini_domains_list = """[DOMAINS]
|
||||||
# Return converted valid HTML characters #
|
"""
|
||||||
#----------------------------------------#
|
|
||||||
def convert_altname(altname):
|
|
||||||
altname = altname.replace('<', '<')
|
|
||||||
altname = altname.replace('>', '>')
|
|
||||||
altname = altname.replace('"', '"')
|
|
||||||
altname = altname.replace("'", ''')
|
|
||||||
|
|
||||||
return altname
|
|
||||||
|
|
||||||
|
|
||||||
#=======================#
|
|
||||||
# Return sum of srcfile #
|
|
||||||
# src: True = Content #
|
|
||||||
# False = URI #
|
|
||||||
#-----------------------#
|
|
||||||
def get_filesum(path, src):
|
|
||||||
file_sum = blake2b(digest_size=4)
|
|
||||||
|
|
||||||
if src: file_sum.update(open(path, 'rb').read())
|
|
||||||
else: file_sum.update(path.encode())
|
|
||||||
return file_sum.hexdigest()
|
|
||||||
|
|
||||||
|
|
||||||
#==============================#
|
|
||||||
# Set and return date and time #
|
|
||||||
#------------------------------#
|
|
||||||
def nowdate():
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
return(now.strftime('%Y-%m-%d %H:%M:%S'))
|
|
||||||
|
|
||||||
|
|
||||||
#======================#
|
|
||||||
# Open and edit a file #
|
|
||||||
#----------------------#
|
|
||||||
def edit_file(edit_file):
|
|
||||||
if not os.path.exists(edit_file):
|
|
||||||
logs.out("1", edit_file, True)
|
|
||||||
|
|
||||||
try:
|
|
||||||
file_edit = subprocess.run(
|
|
||||||
[
|
|
||||||
'/usr/bin/nano',
|
|
||||||
'--linenumbers',
|
|
||||||
edit_file
|
|
||||||
]
|
|
||||||
)
|
|
||||||
except:
|
|
||||||
logs.out("1", "/usr/bin/nano", True)
|
|
||||||
|
|
||||||
|
|
||||||
#=====================#
|
|
||||||
# Create a file #
|
|
||||||
# Or append text #
|
|
||||||
# new: True = create #
|
|
||||||
# False = Append #
|
|
||||||
#---------------------#
|
|
||||||
def set_file(path, new, text):
|
|
||||||
if new: opt = "w"
|
|
||||||
else: opt = "a"
|
|
||||||
|
|
||||||
try:
|
|
||||||
file = open(path, opt)
|
|
||||||
file.write(text)
|
|
||||||
file.close()
|
|
||||||
if opt == 'w':
|
|
||||||
logs.out("32", path, False)
|
|
||||||
except:
|
|
||||||
logs.out("4", path, True)
|
|
||||||
|
|
||||||
|
|
||||||
#==========================#
|
|
||||||
# Get CSS from line if set #
|
|
||||||
#--------------------------#
|
|
||||||
def get_css(line):
|
|
||||||
# Use this default, if not in conf
|
|
||||||
css = 'tyto'
|
|
||||||
|
|
||||||
try: css = dom.css
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
# Get CSS from line
|
|
||||||
try: css = re.search (r'(?<=' ') +([^ -.]*)', line).group(1)
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
return css
|
|
||||||
|
|
||||||
|
|
||||||
#==============================#
|
|
||||||
# Replace escaped markers #
|
|
||||||
# check: with "" #
|
|
||||||
# wip: with altternate #
|
|
||||||
# reverse: True/False #
|
|
||||||
#------------------------------#
|
|
||||||
def protect_escaped(post_bottom, reverse):
|
|
||||||
for m1, m2, h1, h2, n, e1, e2, r1, r2 in markers_tags:
|
|
||||||
|
|
||||||
# In check mode, No need to keep escaped markers
|
|
||||||
if args.action == "check":
|
|
||||||
r1 = r2 = ''
|
|
||||||
|
|
||||||
if reverse:
|
|
||||||
post_bottom = post_bottom.replace(r1, m1)
|
|
||||||
post_bottom = post_bottom.replace(r2, m2)
|
|
||||||
else:
|
|
||||||
post_bottom = post_bottom.replace(e1, r1)
|
|
||||||
post_bottom = post_bottom.replace(e2, r2)
|
|
||||||
|
|
||||||
return post_bottom
|
|
||||||
|
|
||||||
|
|
||||||
#=============================================#
|
|
||||||
# First check process to protect contents #
|
|
||||||
# Protect block-Codes, quotes #
|
|
||||||
# Also remove empty/commented lines #
|
|
||||||
# Used in check and wip #
|
|
||||||
# check: create string without quotes, bcodes #
|
|
||||||
# wip: remplace quotes, bcode with base64 #
|
|
||||||
#---------------------------------------------#
|
|
||||||
def protect_bcodes_quotes(process, post_bottom):
|
|
||||||
global protect_article
|
|
||||||
global nbr_titles, nbr_bcodes, nbr_quotes # Stats for DB
|
|
||||||
|
|
||||||
in_bcode = in_quote = False
|
|
||||||
protect_article = ''
|
|
||||||
bcode = quote = '' # Only for wip process
|
|
||||||
|
|
||||||
for line in post_bottom.rsplit('\n'):
|
|
||||||
start_bcode = close_bcode = False
|
|
||||||
start_quote = close_quote = False
|
|
||||||
|
|
||||||
# Settings and counters
|
|
||||||
#----------------------
|
|
||||||
# Bcode (at close, replace with base64)
|
|
||||||
if not in_quote:
|
|
||||||
if line.startswith(block_tags[2][0]): # Open
|
|
||||||
start_bcode = True
|
|
||||||
in_bcode = True
|
|
||||||
elif line.startswith(block_tags[2][1]): # Close
|
|
||||||
close_bcode = True
|
|
||||||
in_bcode = False
|
|
||||||
if process == "wip":
|
|
||||||
bcode = '%s\n%s'%(bcode, line)
|
|
||||||
bcode = convert_altname(bcode)
|
|
||||||
b64_bcode = b64('Encode', bcode, 'B64.', '.B64')
|
|
||||||
line = b64_bcode
|
|
||||||
|
|
||||||
# Quote (at close, replace with base64)
|
|
||||||
if not in_bcode:
|
|
||||||
if line.startswith(block_tags[1][0]): # Open
|
|
||||||
start_quote = True
|
|
||||||
in_quote = True
|
|
||||||
elif line.startswith(block_tags[1][1]): # Close
|
|
||||||
close_quote = True
|
|
||||||
in_quote = False
|
|
||||||
if process == "wip":
|
|
||||||
quote = '%s\n%s'%(quote, line)
|
|
||||||
quote = convert_altname(quote)
|
|
||||||
b64_quote = b64('Encode', quote, 'Q64.', '.Q64')
|
|
||||||
line = b64_quote
|
|
||||||
|
|
||||||
|
|
||||||
# Counters and keep tags for check process
|
|
||||||
#-----------------------------------------
|
|
||||||
if process == "check":
|
|
||||||
if in_bcode and not start_bcode \
|
|
||||||
or in_quote and not start_quote :
|
|
||||||
line = '#-Protectedline-'
|
|
||||||
|
|
||||||
# Set new article content for wip process
|
|
||||||
#----------------------------------------
|
|
||||||
elif process == "wip":
|
|
||||||
# Remove empty line and comments
|
|
||||||
if not in_quote and not in_bcode:
|
|
||||||
if not line:
|
|
||||||
continue
|
|
||||||
elif line.startswith('#') and not line.startswith(titles_user):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# bcode convertion to base64
|
|
||||||
elif in_bcode:
|
|
||||||
# Convert lines to b64
|
|
||||||
if not bcode: bcode = line
|
|
||||||
else: bcode = '%s\n%s'%(bcode, line)
|
|
||||||
line = ''
|
|
||||||
continue
|
|
||||||
|
|
||||||
elif in_quote:
|
|
||||||
# Convert lines to b64
|
|
||||||
if not quote: quote = line
|
|
||||||
else: quote = '%s\n%s'%(quote, line)
|
|
||||||
line = ''
|
|
||||||
continue
|
|
||||||
|
|
||||||
|
|
||||||
# Set new content
|
|
||||||
#----------------
|
|
||||||
# check: remove quote/bcode, keep tags
|
|
||||||
# wip: replace close tag with quote/bcode (keep in open tag)
|
|
||||||
if not protect_article: protect_article = line
|
|
||||||
else: protect_article = '%s\n%s'%(protect_article, line)
|
|
||||||
|
|
||||||
|
|
||||||
# Clean in wip process for new quote/bcode
|
|
||||||
if process == "wip":
|
|
||||||
if close_bcode: bcode = b64_bcode = ''
|
|
||||||
if close_quote: quote = b64_quote = ''
|
|
||||||
|
|
||||||
|
|
||||||
#=======================================#
|
|
||||||
# Protec iCodes #
|
|
||||||
# Used in check and wip #
|
|
||||||
# Methode: iterate (c)haracter in lines #
|
|
||||||
# check: remove icdoe #
|
|
||||||
# wip: convert to b64 #
|
|
||||||
#---------------------------------------#
|
|
||||||
def protect_icodes(post_bottom):
|
|
||||||
global nbr_icodes
|
|
||||||
|
|
||||||
# Get only lines that contains code
|
|
||||||
in_icode = ok_icode = go_icode = False
|
|
||||||
for ln, line in enumerate(post_bottom.rsplit('\n')):
|
|
||||||
if not icode_tags[0] in line or \
|
|
||||||
not icode_tags[1] in line:
|
|
||||||
continue
|
|
||||||
|
|
||||||
code = ""
|
|
||||||
for i, c in enumerate(line):
|
|
||||||
if c == "_":
|
|
||||||
try:
|
|
||||||
# {_
|
|
||||||
if line[i-1] == icode_tags[0][0] and line[i-2] != "\\":
|
|
||||||
in_icode = True
|
|
||||||
ok_icode = False
|
|
||||||
#go_icode = True
|
|
||||||
continue
|
|
||||||
# _}
|
|
||||||
elif line[i+1] == icode_tags[1][1] and line[i-2] != "\\":
|
|
||||||
in_icode = False
|
|
||||||
ok_icode = True
|
|
||||||
go_icode = False
|
|
||||||
except:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if in_icode:
|
|
||||||
ok_icode = False
|
|
||||||
code = "%s%s"%(code, c)
|
|
||||||
|
|
||||||
# End icode
|
|
||||||
if ok_icode:
|
|
||||||
nbr_icodes += 1
|
|
||||||
tyto_code = "%s%s%s"%(icode_tags[0], code, icode_tags[1])
|
|
||||||
|
|
||||||
if args.action == "check":
|
|
||||||
post_bottom = \
|
|
||||||
post_bottom = post_bottom.replace(tyto_code , '')
|
|
||||||
|
|
||||||
elif args.action == "wip":
|
|
||||||
code = convert_altname(code) # HTML sympbols
|
|
||||||
html_code = "%s%s%s"%(
|
|
||||||
icode_tags[2], code, icode_tags[3])
|
|
||||||
b64_code = b64('Encode', html_code, 'I64.', '.I64')
|
|
||||||
post_bottom = post_bottom.replace(tyto_code, b64_code)
|
|
||||||
|
|
||||||
|
|
||||||
# Reset for next
|
|
||||||
code = tyto_code = html_code = b64_code = ""
|
|
||||||
ok_icode = False
|
|
||||||
|
|
||||||
post_bottom = post_bottom.replace("\\%s"%icode_tags[0], icode_tags[0])
|
|
||||||
post_bottom = post_bottom.replace("\\%s"%icode_tags[1], icode_tags[1])
|
|
||||||
|
|
||||||
return post_bottom
|
|
||||||
|
|
||||||
|
|
||||||
#=====================================#
|
|
||||||
# Encode/Decode string to/from base64 #
|
|
||||||
# Data protection in UTF8 #
|
|
||||||
#-------------------------------------#
|
|
||||||
def b64(action, content, before, after):
|
|
||||||
if action == 'Encode':
|
|
||||||
global b64_content
|
|
||||||
|
|
||||||
b64_base64 = ''
|
|
||||||
content_bytes = content.encode("utf8")
|
|
||||||
base64_bytes = base64.b64encode(content_bytes)
|
|
||||||
b64_content = before + base64_bytes.decode("utf8") + after
|
|
||||||
return b64_content
|
|
||||||
|
|
||||||
elif action == 'Decode':
|
|
||||||
global src_content
|
|
||||||
|
|
||||||
src_content = ''
|
|
||||||
content_bytes = content.encode("utf8")
|
|
||||||
base64_bytes = base64.b64decode(content_bytes)
|
|
||||||
src_content = base64_bytes.decode("utf8")
|
|
||||||
return src_content
|
|
||||||
|
|
||||||
else:
|
|
||||||
print("Options: 'Encode', 'Decode'")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
#====================================#
|
|
||||||
# Replace in post_db #
|
|
||||||
# Used for wip and publish #
|
|
||||||
# to replace hash and date when done #
|
|
||||||
#------------------------------------#
|
|
||||||
def change_in_db(db_file, db_values):
|
|
||||||
try: post_db = open(db_file, "r").read()
|
|
||||||
except: logs.out("1", db_file, True)
|
|
||||||
|
|
||||||
for value in db_values:
|
|
||||||
old_value = re.findall(r'%s\s+=\s+%s'%(
|
|
||||||
value[0],value[1]
|
|
||||||
), post_db
|
|
||||||
)[0]
|
|
||||||
new_value = old_value.replace(value[1], value[2])
|
|
||||||
if new_value != old_value:
|
|
||||||
post_db = post_db.replace(old_value, new_value)
|
|
||||||
|
|
||||||
set_file(db_file, 'New', post_db)
|
|
||||||
|
|
||||||
|
|
||||||
#===================================#
|
|
||||||
# Copy files used by article to srv #
|
|
||||||
#-----------------------------------#
|
|
||||||
def files_to_srv(server):
|
|
||||||
import db
|
|
||||||
for uri in db.uris:
|
|
||||||
|
|
||||||
# Extract Directories from uri file
|
|
||||||
d_in = uri.split("/")[-1]
|
|
||||||
d_in = uri.rsplit(d_in)[0]
|
|
||||||
|
|
||||||
# Destination file and directories according to server
|
|
||||||
# (remove last / from domain directory value)
|
|
||||||
f_src = '%s%s'%(dom.articles_d[:-1], uri)
|
|
||||||
if server == 'wip':
|
|
||||||
f_dst = '%s%s'%(dom.srv_wip[:-1], uri)
|
|
||||||
d_dst = '%s%s'%(dom.srv_wip[:-1], d_in)
|
|
||||||
elif server == 'www':
|
|
||||||
f_dst = '%s%s'%(dom.srv_www[:-1], uri)
|
|
||||||
d_dst = '%s%s'%(dom.srv_www[:-1], d_in)
|
|
||||||
|
|
||||||
# Create sub-directories in server
|
|
||||||
try:
|
|
||||||
if os.makedirs(d_dst, exist_ok=True):
|
|
||||||
logs.out("33", d_dst, False)
|
|
||||||
except:
|
|
||||||
logs.out('4', d_dst, True)
|
|
||||||
|
|
||||||
# COpy files to server
|
|
||||||
try:
|
|
||||||
shutil.copy2(f_src, f_dst)
|
|
||||||
logs.out("32", f_dst, False)
|
|
||||||
except:
|
|
||||||
logs.out('4', f_dst, True)
|
|
||||||
|
|
||||||
# Copy source post file in server
|
|
||||||
# if article_code is True in domain DB
|
|
||||||
if dom.article_code:
|
|
||||||
if server == "wip": base_srv = dom.srv_wip
|
|
||||||
elif server == "www": base_srv = dom.srv_www
|
|
||||||
|
|
||||||
f_dst = "%s%s"%(base_srv, db.short_src)
|
|
||||||
try:
|
|
||||||
shutil.copy2(db.post_src, f_dst)
|
|
||||||
logs.out("32", f_dst, False)
|
|
||||||
except:
|
|
||||||
logs.out('4', f_dst, True)
|
|
||||||
|
|
||||||
|
|
||||||
#========================================#
|
|
||||||
# For mass treatment, show message about #
|
|
||||||
#----------------------------------------#
|
|
||||||
def show_multi_message(server, srv_dir):
|
|
||||||
if args.target == "added":
|
|
||||||
print(" │ %s '%s' > %s"%(langs.site.srv_added, server, srv_dir))
|
|
||||||
|
|
||||||
elif args.target == "updated":
|
|
||||||
print(" │ %s '%s' > %s "%(langs.site.srv_updated, server, srv_dir))
|
|
||||||
|
|
||||||
elif args.target == "again":
|
|
||||||
print(" │ %s '%s' > %s"%(langs.site.srv_again, server, srv_dir))
|
|
||||||
|
|
||||||
|
# Domain keys that can be empty
|
||||||
|
opt_domain_keys = ("legals_url", "terms_url", "statuses_url")
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Tyto - Littérateur
|
||||||
|
|
||||||
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# XMPP: echolib (im@echolib.re)
|
||||||
|
#
|
||||||
|
# Description: When user wants to set something (mainly in domain)
|
||||||
|
# File: /var/lib/tyto/program/set.py
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-------------------------
|
||||||
|
# Funny Stats Project
|
||||||
|
#-------------------------
|
||||||
|
# file lines :
|
||||||
|
# file comments :
|
||||||
|
# file functions:
|
||||||
|
# file program :
|
||||||
|
#--------------------------
|
||||||
|
|
||||||
|
import langs, forms
|
||||||
|
|
||||||
|
|
||||||
|
#====================================#
|
||||||
|
# Manage arguments from command line #
|
||||||
|
# Specific to action "set #
|
||||||
|
#------------------------------------#
|
||||||
|
def manage(action, target):
|
||||||
|
do = {
|
||||||
|
"title" : forms.ask_domain_title,
|
||||||
|
"date" : forms.ask_domain_date,
|
||||||
|
"about" : forms.ask_domain_about,
|
||||||
|
"mail" : forms.ask_domain_mail,
|
||||||
|
"lang" : forms.ask_domain_lang,
|
||||||
|
"server" : forms.ask_domain_server,
|
||||||
|
}
|
||||||
|
|
||||||
|
do[target]()
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,89 +1,64 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Name: Tyto - Littérateur
|
# Tyto - Littérateur
|
||||||
# Type: translation file
|
|
||||||
# Description: Only for logs (internal messages) [en]
|
|
||||||
# file: logs_en.py
|
|
||||||
# Folder: /var/lib/tyto/translations/
|
|
||||||
# By echolib (XMPP: im@echolib.re)
|
|
||||||
# Repo: https://git.a-lec.org/echolib/tyto.git
|
|
||||||
# License: GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007
|
|
||||||
|
|
||||||
#**********************************************************************
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
|
|
||||||
# Generic
|
# This program is free software: you can redistribute it and/or modify
|
||||||
sidebar = 'Sidebar'
|
# it under the terms of the GNU General Public License as published by
|
||||||
navbar = 'Navbar'
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
meta_t = '<meta> tag'
|
# (at your option) any later version.
|
||||||
time_t = '<time> tag'
|
|
||||||
metas = 'Metas Tags'
|
|
||||||
footer = 'Footer'
|
|
||||||
line = "Ligne"
|
|
||||||
no_up = "not updated"
|
|
||||||
ntd = "Nothing to do"
|
|
||||||
all_ok = "All is OK"
|
|
||||||
nonewpost = "No new article"
|
|
||||||
unused_r = "Unused ressource"
|
|
||||||
unused_c = "Unused database value"
|
|
||||||
db_inv = "Corrupted article's database"
|
|
||||||
err_arg = "Argument error"
|
|
||||||
no_arg = "Unused argument"
|
|
||||||
no_fidi = "Black Hole: no file or directory here"
|
|
||||||
dom_ina = "Inactive domain"
|
|
||||||
dom_inc = "Incomplete domain"
|
|
||||||
dom_act = "Active domain"
|
|
||||||
dom_cor = "Corrupted domain"
|
|
||||||
data_inc = "Incomplete data"
|
|
||||||
data_inv = "Invalid data"
|
|
||||||
dom_no = "No domain found"
|
|
||||||
|
|
||||||
file_c = "File created"
|
# This program is distributed in the hope that it will be useful,
|
||||||
file_n = "File changed"
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
file_e = "File exists"
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
dir_c = "Directory created"
|
# GNU General Public License for more details.
|
||||||
dir_e = "Directory exists"
|
|
||||||
post_exists = "Ab article already exists"
|
|
||||||
|
|
||||||
# chk
|
# You should have received a copy of the GNU General Public License
|
||||||
shebang_r= 'Remove shebang'
|
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||||
nycheck = "Article not yet checked"
|
|
||||||
was_chk = "Article was 'check'"
|
|
||||||
st_chk_o = "Old 'check' status"
|
|
||||||
post_inc = "Unused in article"
|
|
||||||
post_inv = "Article not valid"
|
|
||||||
post_val = "Article is valid"
|
|
||||||
title_no = "Empty title"
|
|
||||||
unused_p = "Empty article"
|
|
||||||
|
|
||||||
# wip
|
#----------------------------------------------------------------------
|
||||||
nywip = "Article not yet wip"
|
# XMPP: echolib (im@echolib.re)
|
||||||
was_wip = "Article was 'wip'"
|
#
|
||||||
|
# Description: English logs translation file
|
||||||
|
# File: /var/lib/tyto/translations/logs_en.py
|
||||||
|
#
|
||||||
|
# How to translate:
|
||||||
|
# - create filename logs_xx.py in /var/lib/tyto/translations/
|
||||||
|
# where xx are 2 first lang letters (es, for spanish...)
|
||||||
|
# - copy its contents and translate values
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
# www
|
# Note: python file
|
||||||
was_pub = "Article was published"
|
|
||||||
|
|
||||||
# Misc
|
# Réponses valides (! NON sensible à la case : oui = OUI, Oui...)
|
||||||
post_nfd = "Page not found"
|
ok = ("yes", "y")
|
||||||
post_yfd = "Page found"
|
|
||||||
static_y = "Page is static"
|
|
||||||
static_n = "Page not static"
|
|
||||||
status_n = "Status: unused"
|
|
||||||
status_o = "Status: old"
|
|
||||||
status_s = "Status: up to date"
|
|
||||||
|
|
||||||
check_m = "Check manually"
|
|
||||||
post_chg = "Article changed: 'check' it first"
|
|
||||||
sep_inv = "Unused separator in article"
|
|
||||||
unused_v = "Unused value in article"
|
|
||||||
unused_t = "Unused value in header"
|
|
||||||
mark_np = "Not paired marks"
|
|
||||||
symb_np = "Not paired symbols"
|
|
||||||
snpic_d = "Using default snpic. Not found"
|
|
||||||
anch_nu = "Anchor not uniq"
|
|
||||||
nyfile = "file not yet created"
|
|
||||||
add = "Add:"
|
|
||||||
nomods = "Create HTML modules first"
|
|
||||||
status_r = "Checking unused ressources..."
|
|
||||||
was_wip = "Article already 'wip'"
|
|
||||||
|
|
||||||
|
|
||||||
laterout = "Maybe later..."
|
#
|
||||||
|
# Show HELP
|
||||||
|
#
|
||||||
|
help_contents = """
|
||||||
|
tyto [action] [target] [options]
|
||||||
|
[action]
|
||||||
|
new : create new domain (reset with -F)
|
||||||
|
set : set website lang, domain values (title, server...)
|
||||||
|
check :
|
||||||
|
wip :
|
||||||
|
publish :
|
||||||
|
|
||||||
|
[target]
|
||||||
|
domain : all about current domain home
|
||||||
|
domains : list all registred domains
|
||||||
|
title : [set]: domain title
|
||||||
|
date : [set]: domain creation date
|
||||||
|
about : [set]: domain description
|
||||||
|
mail : [set]: domain admin mail
|
||||||
|
tags : [set]: domain tags (added to all articles)
|
||||||
|
lang :
|
||||||
|
server : [set]: server local URI
|
||||||
|
|
||||||
|
[options] ; multi-set
|
||||||
|
--force, -F : force doing things...
|
||||||
|
--debug, -D : show more logs
|
||||||
|
--errors, -E : Show only warn and error logs
|
||||||
|
"""
|
||||||
|
|
|
@ -1,88 +1,108 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# Nom: Tyto - Littérateur
|
# Tyto - Littérateur
|
||||||
# Type: Fichier de traduction
|
|
||||||
# Description: Seulement pour les logs (messages internes) [fr]
|
|
||||||
# Fichier: logs_fr.py
|
|
||||||
# Dossier: /var/lib/tyto/translations/
|
|
||||||
# Par echolib (XMPP: im@echolib.re)
|
|
||||||
# Dépôt: https://git.a-lec.org/echolib/tyto.git
|
|
||||||
# Licence: GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007
|
|
||||||
|
|
||||||
#**********************************************************************
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
|
|
||||||
# Generique
|
# This program is free software: you can redistribute it and/or modify
|
||||||
sidebar = 'Barre Latérale'
|
# it under the terms of the GNU General Public License as published by
|
||||||
navbar = 'Barre de navigation'
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
meta_t = 'Balise <meta>'
|
# (at your option) any later version.
|
||||||
time_t = 'Balise <time>'
|
|
||||||
metas = 'Balises Metas'
|
|
||||||
footer = "Pied de Page"
|
|
||||||
line = "Line"
|
|
||||||
no_up = "non mise à jour"
|
|
||||||
ntd = "Rien à faire"
|
|
||||||
all_ok = "Tout va bien"
|
|
||||||
nonewpost = "Rien de nouveau"
|
|
||||||
unused_r = "Ressource manquante"
|
|
||||||
unused_c = "Valeur de la base de donnée manquante"
|
|
||||||
db_inv = "Base de donnée de l'article corrompue"
|
|
||||||
err_arg = "Erreur d'argument"
|
|
||||||
no_arg = "Argument manquant"
|
|
||||||
no_fidi = "Trou Noir: aucun fichier ou dossier ici"
|
|
||||||
dom_ina = "Domaine inactif"
|
|
||||||
dom_inc = "Domaine incomplet"
|
|
||||||
dom_act = "Domaine actif"
|
|
||||||
dom_cor = "Domaine corrompu"
|
|
||||||
data_inc = "Donnée incomplète"
|
|
||||||
data_inv = "Donnée invalide"
|
|
||||||
dom_no = "Aucun domaine trouvé"
|
|
||||||
file_c = "Fichier créé"
|
|
||||||
file_n = "Fichier modifié"
|
|
||||||
file_e = "Fichier présent"
|
|
||||||
dir_c = "Dossier créé"
|
|
||||||
dir_e = "Dossier présent"
|
|
||||||
post_exists = "Un article existe déjà"
|
|
||||||
|
|
||||||
# chk
|
# This program is distributed in the hope that it will be useful,
|
||||||
shebang_r= 'Enlever le shebang'
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
nycheck = "Article pas encore 'check'"
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
was_chk = "Article déjà vérifié"
|
# GNU General Public License for more details.
|
||||||
st_chk_o = "Statut 'check' Ancien"
|
|
||||||
post_inc = "Donnée manquante dans l'article"
|
|
||||||
post_inv = "Article non valide"
|
|
||||||
post_val = "Article valide"
|
|
||||||
title_no = "Titre vide"
|
|
||||||
unused_p = "Article vide"
|
|
||||||
|
|
||||||
# Wip
|
# You should have received a copy of the GNU General Public License
|
||||||
nywip = "Article pas encore 'wip'"
|
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||||
was_wip = "Article déjà 'wip'"
|
|
||||||
|
|
||||||
# www
|
#----------------------------------------------------------------------
|
||||||
was_pub = "Article déjà publié"
|
# XMPP: echolib (im@echolib.re)
|
||||||
|
#
|
||||||
|
# Description: Fichier français de traduction des logs
|
||||||
|
# File: /var/lib/tyto/translations/logs_fr.py
|
||||||
|
#
|
||||||
|
# Comment traduire :
|
||||||
|
# - créer un fichier nommé logs_xx.py dans /var/lib/tyto/translations/
|
||||||
|
# oû xx sont les 2 première lettres de la langue (es, pour espagnol...)
|
||||||
|
# - Copier ce contenu dedans, et traduire les variables
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
# Misc
|
# Rappel: Fichier au format python
|
||||||
post_nfd = "Page non présente"
|
|
||||||
post_yfd = "Page présente"
|
|
||||||
static_y = "Page statique"
|
|
||||||
status_n = "Statut : non présent"
|
|
||||||
status_o = "Statut : ancien"
|
|
||||||
status_s = "Statut : à jour"
|
|
||||||
|
|
||||||
static_n = "Page non statique"
|
# Réponses valides (! NON sensible à la case : oui = OUI, Oui...)
|
||||||
check_m = "Vérifier manuellement"
|
ok = ("oui", "o")
|
||||||
post_chg = "Article modifié : commencer par 'check'"
|
|
||||||
sep_inv = "Séparateur manquant dans l'article"
|
# Form
|
||||||
unused_v = "Valeur manquante dans l'article"
|
q = " ?"
|
||||||
unused_t = "Valeur manquante dans l'entête"
|
configure_domain = "Configurer le domaine"
|
||||||
mark_np = "Marqueurs non jumelés"
|
domain_title = "Titre du domaine"
|
||||||
symb_np = "Symboles non jumelés"
|
domain_date = "Date de création"
|
||||||
snpic_d = "snpic utilisé par défaut. Manquant"
|
domain_about = "Description du domaine"
|
||||||
anch_nu = "Ancre non unique"
|
domain_mail = "Courriel de l'administration"
|
||||||
nyfile = "Fichier pas encore créé"
|
domain_tags = "Mots-clés génériques [1,2,3]"
|
||||||
|
domain_lang = "Langue du site web"
|
||||||
|
domain_srv = "URI du serveur"
|
||||||
|
|
||||||
|
# logs for debug
|
||||||
|
#---------------
|
||||||
|
# Errors
|
||||||
|
err_arg = "Argument invalide"
|
||||||
|
err_hole = "Dossier courant invalide"
|
||||||
|
err_date = "Format de date invalide"
|
||||||
|
err_lang = "Format de langue invalide"
|
||||||
|
err_dir = "Dossier non compatible"
|
||||||
|
err_no_dir = "Dossier inexistant"
|
||||||
|
err_cd = "Dossier non créé"
|
||||||
|
err_no_file = "Fichier manquant"
|
||||||
|
err_cr_file = "Fichier non créé"
|
||||||
|
|
||||||
|
# Warnings
|
||||||
|
warn_no_dom = "Domaine non configuré"
|
||||||
|
reset_dom = "RÉINITIALISE le domaine"
|
||||||
|
|
||||||
|
# infos
|
||||||
|
load_file = "Chargement du fichier"
|
||||||
|
lang_logs_sys = "Langue des logs"
|
||||||
|
website_lang = "Langue du site web"
|
||||||
|
domains_no = "Aucun domaine trouvé"
|
||||||
|
domain_found = "Domaine présent"
|
||||||
|
domain_created = "Domaine déjà créé"
|
||||||
|
domain_updated = "Domaine mis à jour"
|
||||||
|
domain_new = "Domaine créé"
|
||||||
|
created_dir = "Dossier créé"
|
||||||
|
created_file = "Fichier créé"
|
||||||
|
updated_file = "Fichier mis à jour"
|
||||||
|
later = "Peut-être plus targ..."
|
||||||
|
|
||||||
|
|
||||||
add = "Ajout:"
|
|
||||||
nomods = "Créer d'abord les modules HTML"
|
|
||||||
status_r = "Vérification des ressources manquantes..."
|
|
||||||
|
|
||||||
laterout = "Pour plus tard..."
|
#
|
||||||
|
# Show HELP
|
||||||
|
#
|
||||||
|
help_contents = """
|
||||||
|
tyto [action] [target] [options]
|
||||||
|
[action]
|
||||||
|
new : créer un nouveau domaine (réinitialisé avec -F)
|
||||||
|
set : définir la langue du site web, du domaine (titre, serveur...)
|
||||||
|
show : [domains]
|
||||||
|
check :
|
||||||
|
wip :
|
||||||
|
publish :
|
||||||
|
|
||||||
|
[target]
|
||||||
|
domain : pour tout ce qui concerne un domaine
|
||||||
|
domains : montre tous les domaines enregistrés
|
||||||
|
title : [set]: titre du domaine
|
||||||
|
date : [set]: date de création du domaine
|
||||||
|
about : [set]: description du domaine
|
||||||
|
mail : [set]: courriel de l'administrateur
|
||||||
|
tags : [set]: étiquettes du domaine (ajoutées aux articles)
|
||||||
|
lang :
|
||||||
|
server : [set]: URI du serveur local
|
||||||
|
|
||||||
|
[options] ; multiples
|
||||||
|
--force, -F : forcer à faire quelque chose...
|
||||||
|
--debug, -D : montrer plus de logs
|
||||||
|
--errors, -E : montrer uniquement les avertissement et erreurs
|
||||||
|
"""
|
||||||
|
|
|
@ -1,342 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Name: Tyto - Littérateur
|
|
||||||
# Type: translation file
|
|
||||||
# Description: Only for website [en]
|
|
||||||
# file: site_en.py
|
|
||||||
# Folder: /var/lib/tyto/translations/
|
|
||||||
# By echolib (XMPP: im@echolib.re)
|
|
||||||
# Repo: https://git.a-lec.org/echolib/tyto.git
|
|
||||||
# License: GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007
|
|
||||||
|
|
||||||
#**********************************************************************
|
|
||||||
|
|
||||||
# IMPORTANT Instructions
|
|
||||||
#-----------------------
|
|
||||||
# This is a python file, so... DO NOT REMOVE:
|
|
||||||
# - "#"
|
|
||||||
# - "%s", "%d"
|
|
||||||
# - "\n"
|
|
||||||
# - "+ \"
|
|
||||||
|
|
||||||
# Keep array ! ('','',)
|
|
||||||
yes = ("y", "yes",)
|
|
||||||
|
|
||||||
# Generic
|
|
||||||
article = "Article"
|
|
||||||
links = "links"
|
|
||||||
sidebar = 'Sidebar'
|
|
||||||
navbar = 'Navbar'
|
|
||||||
metas = 'Metas Tags'
|
|
||||||
footer = 'Footer'
|
|
||||||
title = 'Title'
|
|
||||||
File = 'File'
|
|
||||||
name = 'Name'
|
|
||||||
by = "by"
|
|
||||||
le = "the"
|
|
||||||
fo = "for"
|
|
||||||
proceed = "Continue"
|
|
||||||
q = '?'
|
|
||||||
i = '!'
|
|
||||||
pp = ":"
|
|
||||||
|
|
||||||
# Website
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# Misc.
|
|
||||||
source_code = "Source code"
|
|
||||||
home = "Home"
|
|
||||||
go_home = "Go to Homepage"
|
|
||||||
read = "Read"
|
|
||||||
tyto_psrc = "Source code in Tyto format of"
|
|
||||||
w_written = "was written the"
|
|
||||||
w_published = "was published the"
|
|
||||||
written = "written the"
|
|
||||||
author_of = "is the uthor of"
|
|
||||||
|
|
||||||
# Sidebar
|
|
||||||
site_sdb_t = "Featured..."
|
|
||||||
|
|
||||||
# Footer
|
|
||||||
tyto_site_t = "Official website of %s, the Libre websites generator"
|
|
||||||
tyto_git_t = "%s's official source code repository"
|
|
||||||
legal_t = "Legal notice"
|
|
||||||
terms_t = "Terms of Use"
|
|
||||||
terms_s = "T.o.U"
|
|
||||||
law = "Law"
|
|
||||||
about = "About"
|
|
||||||
add_inf = "additional Informations %s"%about.lower()
|
|
||||||
licence = "License"
|
|
||||||
contact = "Contact"
|
|
||||||
mail = "Mail"
|
|
||||||
mail_to = "Contact by %s the admin of"%mail.lower()
|
|
||||||
feed = "Feed"
|
|
||||||
generator = "Generator"
|
|
||||||
|
|
||||||
# Misc for Tyto
|
|
||||||
#--------------
|
|
||||||
# Check
|
|
||||||
check_a = "Check again this article"
|
|
||||||
post_chg = "Article was edited. Check it"
|
|
||||||
new_post = "Create article"
|
|
||||||
|
|
||||||
# Wip
|
|
||||||
wip_new = "Create a new HTML page in 'wip' server again"
|
|
||||||
srv_again = "Create again converted HTMl pages in server"
|
|
||||||
srv_added = "Create missing HTML pages in server"
|
|
||||||
srv_updated = "Update HTMl pages in server"
|
|
||||||
wip_in_mod = "Include static module"
|
|
||||||
|
|
||||||
# publish
|
|
||||||
publish_a = "Publish again this article"
|
|
||||||
rss_c = "Create ATOM/RSS feed"
|
|
||||||
|
|
||||||
# Other
|
|
||||||
uptpl = "Update directory"
|
|
||||||
stats_f = "Articles: %s (%s words)"
|
|
||||||
reg_domains = "Registred domains"
|
|
||||||
sitemap_gen = "Sitemap generated by"
|
|
||||||
sitemap_t = "Sitemap"
|
|
||||||
|
|
||||||
# Form
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
form_edit = "Edit the domain with the form"
|
|
||||||
form_start = ' ├──────────────────────────────────────────────┐\n' + \
|
|
||||||
' │ Configure a new domain for current directory │\n' + \
|
|
||||||
' │ Answer Y/y = yes. Enter to keep {default} │\n' + \
|
|
||||||
' │ Empty Answer cancel process, except for │\n' + \
|
|
||||||
' │ - [Optional] │\n' + \
|
|
||||||
' │ - known {default} value │\n' + \
|
|
||||||
' ├──────────────────────────────────────────────┘'
|
|
||||||
form_warn = ' │\n' + \
|
|
||||||
' ├──────────────────────────────────────┐\n' + \
|
|
||||||
' │ Please, READ the configuration datas │\n' + \
|
|
||||||
' ├──────────────────────────────────────┘'
|
|
||||||
form_ready = ' │\n' + \
|
|
||||||
' ├──────────────────────────────────────┐\n' + \
|
|
||||||
' │ Domain is ready. Have fun, writers ! │\n' + \
|
|
||||||
' └──────────────────────────────────────┘'
|
|
||||||
form_inv = ' │\n' + \
|
|
||||||
' ├─────────────────────────────────────┐\n' + \
|
|
||||||
' │ Domain is INVALID. Try form again ! │\n' + \
|
|
||||||
' └─────────────────────────────────────┘'
|
|
||||||
|
|
||||||
form_opt = "[Optional]"
|
|
||||||
form_url = "URL to official website"
|
|
||||||
form_wip = "URL to 'wip' website"
|
|
||||||
form_db_new = "Created new database"
|
|
||||||
form_trlog = "[2 char.] Logs language"
|
|
||||||
form_srv = "Local server directory"
|
|
||||||
form_logo = "Logo filename"
|
|
||||||
form_fav_f = "Favicon filename !(.png)"
|
|
||||||
form_css_f = "CSS filename"
|
|
||||||
form_rss_f = "Atom/RSS filename"
|
|
||||||
form_rss_i = "Atom/RSS articles' number"
|
|
||||||
form_title = "Website title"
|
|
||||||
form_date = "Domain creation year"
|
|
||||||
form_about = "Domain Description"
|
|
||||||
form_mail = "Webmaster's mail"
|
|
||||||
form_tags = "[comma separated] Domain tags"
|
|
||||||
form_lic = "Domain License"
|
|
||||||
form_licurl = "License URL"
|
|
||||||
form_legal = "Legal Notice URL"
|
|
||||||
form_terms = "Terms of Use URL"
|
|
||||||
form_css = "[alnum] CSS Prefix"
|
|
||||||
form_sep = "[1 char.] Pages titles separator"
|
|
||||||
form_pscode = "Show Article source code"
|
|
||||||
form_relme = 'rel="me" URL'
|
|
||||||
form_trsite = "[2 char.] Website language"
|
|
||||||
form_sdb_i = "Article number"
|
|
||||||
form_activ = "Activate and prepare domain"
|
|
||||||
form_dir_e = "Directory exists"
|
|
||||||
form_dir_c = "Directory created"
|
|
||||||
form_file_e = "File exists"
|
|
||||||
form_file_c = "File created"
|
|
||||||
|
|
||||||
form_reset = "Reset configuration"
|
|
||||||
form_rep = "Replace HTML file"
|
|
||||||
|
|
||||||
|
|
||||||
# Documentation of configuration files
|
|
||||||
#-------------------------------------
|
|
||||||
metas_inf = "Create <meta> tags"
|
|
||||||
metas_doc = \
|
|
||||||
'# For %s\n' + \
|
|
||||||
'# Type text/HTML file\n' + \
|
|
||||||
'# Description Configuration file for HTML <metas> tags\n' + \
|
|
||||||
'# Content inserted in <head> section\n' + \
|
|
||||||
'# File %s\n' + \
|
|
||||||
'# How Insert <metas ...> and <link ...>\n' + \
|
|
||||||
'# Notes - Ony these tags are added :\n' + \
|
|
||||||
'# - <metas>\n' + \
|
|
||||||
'~ - <link>\n' + \
|
|
||||||
'# - Do NOT copy this file to template directory\n' + \
|
|
||||||
'# - These tags are already set'
|
|
||||||
|
|
||||||
navbar_inf = "Create navbar"
|
|
||||||
navbar_doc = \
|
|
||||||
'# For %s\n' + \
|
|
||||||
'# Type: Text file\n' + \
|
|
||||||
'# Description Configuration file for navbar"\n' + \
|
|
||||||
'# (directories\'s list)\n' + \
|
|
||||||
'# Commands tyto new navbar (reset)\n' + \
|
|
||||||
'# tyto wip/publish navbar (Create)\n' + \
|
|
||||||
'# tyto show navbar (show config)\n' + \
|
|
||||||
'# tyto show-wip/show-www navbar (Show HTML)\n' + \
|
|
||||||
'# tyto edit navbar (edit this file)\n' + \
|
|
||||||
'# File %s\n' + \
|
|
||||||
'# Comment 1 folder name per line *1\n' + \
|
|
||||||
'# (from articles/)\n' + \
|
|
||||||
'# not begining with "/"\n' + \
|
|
||||||
'# Order in sidebar position\n' + \
|
|
||||||
'# Remember To avoid 404 error, you must:\n' + \
|
|
||||||
'# - add article index.{tyto}\n' + \
|
|
||||||
'# in set folder\n' + \
|
|
||||||
'# - check and wip article\n' + \
|
|
||||||
'# *1 Option To define a title link:' + \
|
|
||||||
'# - add "# title link"\n' + \
|
|
||||||
'\n# %s\n'%(20 * "-") +\
|
|
||||||
'# Examples :\n' + \
|
|
||||||
'# documentation\n' + \
|
|
||||||
'# about # infos about this website\n' + \
|
|
||||||
'# %s\n\n'%(20 * "-")
|
|
||||||
|
|
||||||
sidebar_inf = "Create sidebar"
|
|
||||||
sidebar_doc = \
|
|
||||||
'# For %s\n' + \
|
|
||||||
'# Type Text file\n' + \
|
|
||||||
'# Description Configuration file for sidebar\n' + \
|
|
||||||
'# (articles\'s list)\n' + \
|
|
||||||
'# File %s\n' + \
|
|
||||||
'# Commands tyto new sidebar (reset)\n' + \
|
|
||||||
'# tyto wip/publish sidebar (Create)\n' + \
|
|
||||||
'# tyto show sidebar (Show config)\n' + \
|
|
||||||
'# tyto show-wip/show-www sidebar (Show HTML)\n' + \
|
|
||||||
'# tyto edit sidebar (edit this file)\n' + \
|
|
||||||
'# How 1 article URI per line\n' + \
|
|
||||||
'# (from articles/)\n' + \
|
|
||||||
'# not begining with "/"\n' + \
|
|
||||||
'# Order in sidebar position\n' + \
|
|
||||||
'# Max articles = %d\n' + \
|
|
||||||
'# Option Tp set sidebar title:\n' + \
|
|
||||||
'# ": Sidebar Title"\n' + \
|
|
||||||
'\n# %s\n'%(20 * "-") + \
|
|
||||||
'# Examples :\n' + \
|
|
||||||
'# : My new articles list'
|
|
||||||
'# index.tyto\n' + \
|
|
||||||
'# dir1/index.tyto\n' + \
|
|
||||||
'# %s\n\n'%(20 * "-")
|
|
||||||
|
|
||||||
footer_inf = "Create footer"
|
|
||||||
footer_doc = \
|
|
||||||
'# For %s\n' + \
|
|
||||||
'# Type text/HTML file\n' + \
|
|
||||||
'# Description Configuration file for footer\n' + \
|
|
||||||
'# File %s\n' + \
|
|
||||||
'# Commands tyto new footer (reset)\n' + \
|
|
||||||
'# tyto wip/publish footer (Create)\n' + \
|
|
||||||
'# tyto show footer (Show config)\n' + \
|
|
||||||
'# tyto show-wip/show-www footer (Show HTML)\n' + \
|
|
||||||
'# tyto edit footer (edit this file)\n' + \
|
|
||||||
'# How Put any HTML code\n' + \
|
|
||||||
'# Notes - Lines are ignored if:\n' + \
|
|
||||||
'# - empty\n' + \
|
|
||||||
'# - begin with "#"\n' + \
|
|
||||||
'# - Do NOT copy to template directory'
|
|
||||||
'# %s\n'%(20 * "-")
|
|
||||||
|
|
||||||
# Help with Tyto commands
|
|
||||||
args_helps = """\n# New domain :
|
|
||||||
- Create directory and go in
|
|
||||||
- Create domain with 'tyto new domain [URL]'
|
|
||||||
- Create .tyto file in directory "articles/"
|
|
||||||
- Use these actions: check > wip > publish
|
|
||||||
! - Modules files are in directory "_configs/"
|
|
||||||
and used to custom some website parts
|
|
||||||
- (css, logo...) files go in "wip/template/"
|
|
||||||
|
|
||||||
# Usage: tyto [action] [target]
|
|
||||||
# [action] > withour [target]
|
|
||||||
version : Show installed version
|
|
||||||
domains : Show installed domains
|
|
||||||
help : Show commands help
|
|
||||||
|
|
||||||
# [action] > According to [target]
|
|
||||||
# Edit a file
|
|
||||||
edit : Source file, configuration module
|
|
||||||
edit-about: [footer] Edit description section in footer
|
|
||||||
or same as [edit-db]
|
|
||||||
edit-db : Edit database/configuration file
|
|
||||||
edit-wip : Edit a file in server 'wip'
|
|
||||||
edit_www : Edit a file in server 'www'
|
|
||||||
new : [domain] Créer un domaine ou le modifier via le formulaire
|
|
||||||
[sidebar, navbar, footer, metas] Create and replace
|
|
||||||
with default module configuration file
|
|
||||||
[filename] (no .tyto) Create article in current folder
|
|
||||||
[sitemap], create new website sitemap
|
|
||||||
|
|
||||||
# Show contents file (with line number)
|
|
||||||
show : Show source file, source configuration module
|
|
||||||
show-about: [footer] Show description footer file
|
|
||||||
or same as [show-db]
|
|
||||||
show-db : Show database/configuration file
|
|
||||||
show-wip : Show a file in server 'wip'
|
|
||||||
show-www : Show a file in server 'www'
|
|
||||||
|
|
||||||
# Create HTML page
|
|
||||||
check : Check the validity of a tyto format file
|
|
||||||
wip : Create article HTML page in server 'wip'
|
|
||||||
force-wip : [file], check, and then, wip
|
|
||||||
preview : [module]/[file], open 'wip' file on default browser
|
|
||||||
publish : Create article HTML page in server 'www'
|
|
||||||
quick-pub : [file], check, wip, publish
|
|
||||||
|
|
||||||
# [target] > According to [action]
|
|
||||||
# Multiple articles
|
|
||||||
updated : Update articles (already checked)
|
|
||||||
again : Force all articles (already checked)
|
|
||||||
added : [check] Search and check for .tyto articles in domain
|
|
||||||
(not yet checked)
|
|
||||||
[wip, publish] Create articles HTML pages
|
|
||||||
that were edited and checked
|
|
||||||
|
|
||||||
# Update modules/files template
|
|
||||||
template : - Create (replace) modules in directory "template/"
|
|
||||||
- [publish] Also, copy all other files from "wip/template/"
|
|
||||||
|
|
||||||
# Domain and files
|
|
||||||
domain : Create or edit a domain
|
|
||||||
[file] : URI file (autocompletion friendly)
|
|
||||||
|
|
||||||
# Modules
|
|
||||||
footer : Footer configuration file
|
|
||||||
metas : <meta>, <link> configuration file
|
|
||||||
navbar : Navbar configuration file
|
|
||||||
sidebar : Sidebar configuration file
|
|
||||||
stats : Stats file (server 'wip' er 'www')
|
|
||||||
sitemap : sitemap.tyto/.html file
|
|
||||||
|
|
||||||
# [option] :
|
|
||||||
--static : Créer une page HTML entièrement statique
|
|
||||||
--no-mods : With [publish template], do not recreate modules
|
|
||||||
"""
|
|
||||||
|
|
||||||
ex_helps = """# Examples :
|
|
||||||
# Check article (according to sub-folder)
|
|
||||||
$ tyto check mysubdir/index.tyto
|
|
||||||
|
|
||||||
# Create (replace) default sidebar configuration file
|
|
||||||
$ tyto new sidebar
|
|
||||||
|
|
||||||
# Edit navbar configuration file
|
|
||||||
$ tyto edit navbar
|
|
||||||
|
|
||||||
# edit doc/index.html in server 'www'
|
|
||||||
$ tyto edit-www doc/index.tyto
|
|
||||||
|
|
||||||
# Create HTML sidebar file in server 'wip'
|
|
||||||
$ tyto wip sidebar
|
|
||||||
|
|
||||||
# Show footer HTML file in server 'wip'
|
|
||||||
$ tyto show-wip footer
|
|
||||||
|
|
||||||
# Create statistics file in serveur 'www'
|
|
||||||
$ tyto publish stats"""
|
|
|
@ -1,339 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# Nom: Tyto - Littérateur
|
|
||||||
# Type: Fichier de traduction
|
|
||||||
# Description: Seulement pour le site web [fr]
|
|
||||||
# Fichier: site_fr.py
|
|
||||||
# Dossier: /var/lib/tyto/translations/
|
|
||||||
# Par echolib (XMPP: im@echolib.re)
|
|
||||||
# Dépôt: https://git.a-lec.org/echolib/tyto.git
|
|
||||||
# Licence: GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007
|
|
||||||
|
|
||||||
#**********************************************************************
|
|
||||||
|
|
||||||
# Instructions IMPORTANTES
|
|
||||||
#-------------------------
|
|
||||||
# Ceci est un fichier python, donc... NE PAS ENLEVER :
|
|
||||||
# - "#"
|
|
||||||
# - "%s", "%d"
|
|
||||||
# - "\n"
|
|
||||||
# - "+ \"
|
|
||||||
|
|
||||||
# Garder ! ('','',)
|
|
||||||
yes = ("o", "oui",)
|
|
||||||
|
|
||||||
# Generic
|
|
||||||
article = "Article"
|
|
||||||
links = "liens"
|
|
||||||
sidebar = 'Barre Latérale'
|
|
||||||
navbar = 'Barre de menu'
|
|
||||||
metas = 'Balises Metas'
|
|
||||||
footer = 'Pied de Page'
|
|
||||||
title = 'Titre'
|
|
||||||
File = 'Fichier'
|
|
||||||
name = 'Nom'
|
|
||||||
by = "par"
|
|
||||||
le = "le"
|
|
||||||
fo = "pour"
|
|
||||||
proceed = "Continuer"
|
|
||||||
q = ' ?'
|
|
||||||
i = ' !'
|
|
||||||
pp = " :"
|
|
||||||
|
|
||||||
# Site web
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
# Divers
|
|
||||||
source_code = "Code source"
|
|
||||||
home = "Accueil"
|
|
||||||
go_home = "Aller à la page d'accueil"
|
|
||||||
read = "À lire"
|
|
||||||
tyto_psrc = "Code source au format Tyto de"
|
|
||||||
w_written = "a été écrit le"
|
|
||||||
w_published = "a été publié le"
|
|
||||||
written = "écrit le"
|
|
||||||
author_of = "est l'auteur de"
|
|
||||||
|
|
||||||
# Barre latérale
|
|
||||||
site_sdb_t = "À l'affiche..."
|
|
||||||
|
|
||||||
# Pied de page
|
|
||||||
tyto_site_t = "Site web officiel du générateur de sites web Libre %s"
|
|
||||||
tyto_git_t = "Dépôt officiel du code source de %s"
|
|
||||||
legal_t = "Mentions légales"
|
|
||||||
terms_t = "Conditions Générales d'Utilisation"
|
|
||||||
terms_s = "C.G.U"
|
|
||||||
law = "Loi"
|
|
||||||
about = "À propos de"
|
|
||||||
add_inf = "Information supplémentaires %s"%about.lower()
|
|
||||||
licence = "Licence"
|
|
||||||
contact = "Contact"
|
|
||||||
mail = "Courriel"
|
|
||||||
mail_to = "Contacter par %s l'administrateur de"%mail.lower()
|
|
||||||
feed = "Flux"
|
|
||||||
generator = "Generateur"
|
|
||||||
|
|
||||||
# Misc for Tyto
|
|
||||||
#--------------
|
|
||||||
# Check
|
|
||||||
check_a = "Vérifier encore l'article"
|
|
||||||
post_chg = "Article édité. Le vérifier"
|
|
||||||
new_post = "Créer l'article"
|
|
||||||
|
|
||||||
# Wip
|
|
||||||
wip_new = "Créer encore une page HTML dans le serveur 'wip'"
|
|
||||||
srv_again = "Créer encore les pages dans le serveur"
|
|
||||||
srv_added = "Créer les pages HTML manquantes dans le serveur"
|
|
||||||
srv_updated = "Mise à jour des pages HTML dans le serveur"
|
|
||||||
wip_in_mod = "Intégration statique des modules"
|
|
||||||
|
|
||||||
# publish
|
|
||||||
publish_a = "Publier encore l'article"
|
|
||||||
rss_c = "Créer le flux ATOM/RSS"
|
|
||||||
|
|
||||||
# Autre
|
|
||||||
uptpl = "Mettre à jour le dossier"
|
|
||||||
stats_f = "Articles : %s (%s mots)"
|
|
||||||
reg_domains = "Domaines enregistrés"
|
|
||||||
sitemap_gen = "Plan du site (sitemap) généré par"
|
|
||||||
sitemap_t = "Plan du site"
|
|
||||||
|
|
||||||
# Formulaire
|
|
||||||
#----------------------------------------------------------------------
|
|
||||||
form_edit = "Éditer le domaine avec le formulaire"
|
|
||||||
form_start = ' ├───────────────────────────────────────────────┐\n' + \
|
|
||||||
' │ Configurer un domaine pour le dossier courant │\n' + \
|
|
||||||
' │ Répondre O/o = Oui. Entrer garde le {default} │\n' + \
|
|
||||||
' │ Sans réponse : arrêt, sauf pour │\n' + \
|
|
||||||
' │ - [Optionnel] │\n' + \
|
|
||||||
' │ - Valeur {default} connue │\n' + \
|
|
||||||
' ├───────────────────────────────────────────────┘'
|
|
||||||
form_warn = ' │\n' + \
|
|
||||||
' ├──────────────────────────────────────────┐\n' + \
|
|
||||||
' │ SVP, lisez les données de configurations │\n' + \
|
|
||||||
' ├──────────────────────────────────────────┘'
|
|
||||||
form_ready = ' │\n' + \
|
|
||||||
' ├─────────────────────────────────────────┐\n' + \
|
|
||||||
' │ Le domaine est prêt. Amusez-vous bien ! │\n' + \
|
|
||||||
' └─────────────────────────────────────────┘'
|
|
||||||
form_inv = ' │\n' + \
|
|
||||||
' ├───────────────────────────────────────────┐\n' + \
|
|
||||||
' │ Le Domaine est INVALIDE. Essayez encore ! │\n' + \
|
|
||||||
' └───────────────────────────────────────────┘'
|
|
||||||
|
|
||||||
form_opt = "[Optionnel]"
|
|
||||||
form_url = "URL du site web officiel"
|
|
||||||
form_wip = "URL du site web 'wip'"
|
|
||||||
form_db_new = "Nouvelle base de données crée"
|
|
||||||
form_trlog = "[2 car.] Langue des messages"
|
|
||||||
form_srv = "Dossier du serveur local"
|
|
||||||
form_logo = "Nom du fichier du logo"
|
|
||||||
form_fav_f = "Nom du fichier favicon !(.png)"
|
|
||||||
form_css_f = "Nom du fichier CSS"
|
|
||||||
form_rss_f = "Nom du fichier Atom/RSS"
|
|
||||||
form_rss_i = "Nombre d'articles Atom/RSS"
|
|
||||||
form_title = "Titre du site web"
|
|
||||||
form_date = "Année de création du domaine"
|
|
||||||
form_about = "Description du domaine"
|
|
||||||
form_mail = "Courriel du webmestre"
|
|
||||||
form_tags = "[séparées par une virgule] Étiquettes du domaine"
|
|
||||||
form_lic = "Licence du domaine"
|
|
||||||
form_licurl = "URL de la licence"
|
|
||||||
form_legal = "URL des mentions légales"
|
|
||||||
form_terms = "URL des CGU"
|
|
||||||
form_css = "[alnum] Préfix CSS"
|
|
||||||
form_sep = "[1 car.] Séparateur des titres de pages"
|
|
||||||
form_pscode = "Montrer le code source des articles"
|
|
||||||
form_relme = 'URL pour rel="me"'
|
|
||||||
form_trsite = "[2 car.] Langue du site web"
|
|
||||||
form_sdb_i = "Nombre d'articles"
|
|
||||||
form_activ = "Activer et preparer le domaine"
|
|
||||||
form_dir_e = "Dossier présent"
|
|
||||||
form_dir_c = "Dossier créé"
|
|
||||||
form_file_e = "Fichier présent"
|
|
||||||
form_file_c = "Fichier créé"
|
|
||||||
|
|
||||||
form_reset = "Réinitialiser la configuration"
|
|
||||||
form_rep = "Remplacer le fichier HTML"
|
|
||||||
|
|
||||||
|
|
||||||
# Documentation des fichiers de configuration
|
|
||||||
#--------------------------------------------
|
|
||||||
metas_inf = "Créer les balises <meta>"
|
|
||||||
metas_doc = \
|
|
||||||
'# Pour %s\n' + \
|
|
||||||
'# Type Fichier text/HTML\n' + \
|
|
||||||
'# Description Fichier de configuration des balises <meta> HTML \n' + \
|
|
||||||
'# Contenu inséré dans la section <head>\n' + \
|
|
||||||
'# Fichier %s\n' + \
|
|
||||||
'# Comment Insérer des balises <metas ...> et <link ...>\n' + \
|
|
||||||
'# Notes - Sont ajoutées uniquement les balises :\n' + \
|
|
||||||
'# - <metas>\n' + \
|
|
||||||
'~ - <link>\n' + \
|
|
||||||
'# - Ne PAS copier ce fichier dans le dossier template\n' + \
|
|
||||||
'# - Les balises suivantes sont déjà présentes'
|
|
||||||
|
|
||||||
navbar_inf = "Créer la barre de menu"
|
|
||||||
navbar_doc = \
|
|
||||||
'# Pour %s\n' + \
|
|
||||||
'# Type fichier texte\n' + \
|
|
||||||
'# Description Utilisé par "wip/publish navbar"\n' + \
|
|
||||||
'# (Liste des dossiers)\n' + \
|
|
||||||
"# Commandes tyto new navbar (réinitialiser)\n" + \
|
|
||||||
'# tyto wip/publish navbar (créer)\n' + \
|
|
||||||
'# tyto show navbar (afficher la configuration)\n' + \
|
|
||||||
'# tyto show-wip/show-www navbar (afficher l\'HTML)\n' + \
|
|
||||||
'# tyto edit navbar (editer ce fichier)\n' + \
|
|
||||||
'# Fichier %s\n' + \
|
|
||||||
'# Comment 1 nom de dossier par ligne *1\n' + \
|
|
||||||
'# (depuis articles/)\n' + \
|
|
||||||
'# Ne commence pas par "/"\n' + \
|
|
||||||
'# L\'ordre définit la position\n' + \
|
|
||||||
'# Note Pour éviter l\'erreur 404 :\n' + \
|
|
||||||
'# - ajouter un article index.{ext}\n' + \
|
|
||||||
'# dans le dossier mentionné\n' + \
|
|
||||||
'# - check et wip sur l\'article\n' + \
|
|
||||||
'# *1 Option Pour définir un titre de lien :\n' + \
|
|
||||||
'# - ajouter "# titre du lien"\n' + \
|
|
||||||
'\n# %s\n'%(20 * "-") +\
|
|
||||||
'# Exemples :\n' + \
|
|
||||||
'# documentation\n' + \
|
|
||||||
'# a-propos # Informations concernant ce site\n' + \
|
|
||||||
'# %s\n\n'%(20 * "-")
|
|
||||||
|
|
||||||
sidebar_inf = "Créer la barre latérale"
|
|
||||||
sidebar_doc = \
|
|
||||||
'# Pour %s\n' + \
|
|
||||||
'# Type fichier texte\n' + \
|
|
||||||
'# Description Fichier de configuration de la barre latérale\n' + \
|
|
||||||
'# (Liste d\'articles)\n' + \
|
|
||||||
'# Fichier %s\n' + \
|
|
||||||
"# Commandes tyto new sidebar (réinitialiser)\n" + \
|
|
||||||
'# tyto wip/publish sidebar (créer)\n' + \
|
|
||||||
'# tyto show sidebar (afficher la configuration)\n' + \
|
|
||||||
'# tyto show-wip/show-www sidebar (afficher l\'HTML)\n' + \
|
|
||||||
'# tyto edit sidebar (editer ce fichier)\n' + \
|
|
||||||
'# Comment 1 URI de l\'article par ligne\n' + \
|
|
||||||
'# (depuis articles/)\n' + \
|
|
||||||
'# Ne commence pas par "/"\n' + \
|
|
||||||
'# L\'ordre définit la position\n' + \
|
|
||||||
'# Articles max = %d\n' + \
|
|
||||||
'# Option Pour définir un titre à la barre latérale:\n' + \
|
|
||||||
'# ": Titre de la sidebar"\n' + \
|
|
||||||
'\n# %s\n'%(20 * "-") + \
|
|
||||||
'# Exemples :\n' + \
|
|
||||||
'# : Ma liste des nouveaux articles\n' + \
|
|
||||||
'# index.tyto\n' + \
|
|
||||||
'# dir1/index.tyto\n' + \
|
|
||||||
'# %s\n\n'%(20 * "-")
|
|
||||||
|
|
||||||
footer_inf = "Créer le pied de page"
|
|
||||||
footer_doc = \
|
|
||||||
'# Pour %s\n' + \
|
|
||||||
'# Type Fichier text/HTML\n' + \
|
|
||||||
'# Description Fichier de configuration du pied de page\n' + \
|
|
||||||
'# Fichier %s\n' + \
|
|
||||||
"# Commandes tyto new footer (réinitialiser)\n" + \
|
|
||||||
'# tyto wip/publish footer (créer)\n' + \
|
|
||||||
'# tyto show footer (afficher la configuration)\n' + \
|
|
||||||
'# tyto show-wip/show-www footer (afficher l\'HTML)\n' + \
|
|
||||||
'# tyto edit footer (editer ce fichier)\n' + \
|
|
||||||
'# Comment Insérer du code HTML\n' + \
|
|
||||||
'# Notes - Les lignes sont ignorées si :\n' + \
|
|
||||||
'# - vides\n' + \
|
|
||||||
'# - commencent par "#"\n' + \
|
|
||||||
'# - Ne PAS copier ce fichier dans le dossier template\n' + \
|
|
||||||
'# %s\n'%(20 * "-")
|
|
||||||
|
|
||||||
# Help with Tyto commands
|
|
||||||
args_helps = """\n# Nouveau domaine :
|
|
||||||
- Créer un dossier et aller dedans
|
|
||||||
- Créer un domain avec 'tyto new domain [URL]'
|
|
||||||
- Créer un fichier .tyto dans le dossier "articles/"
|
|
||||||
- Utiliser les actions check > wip > publish
|
|
||||||
! - Les fichiers des modules sont dans le dossier "_configs/"
|
|
||||||
et utilisés pour personnaliser certaines parties du site
|
|
||||||
- Les fichier (css, logo...) vont dans le dossier serveur "wip/template/"
|
|
||||||
|
|
||||||
# Usage: tyto [action] [target]
|
|
||||||
# [action] > Sans [target]
|
|
||||||
version : Montre la version installée
|
|
||||||
domains : Montre les domains installés
|
|
||||||
help : Montre l'aide des commandes
|
|
||||||
|
|
||||||
# [action] > Selon l'argument [target]
|
|
||||||
# Modifier un ficher
|
|
||||||
edit : Fichier source, module de configuration
|
|
||||||
edit-db : Modifier une base de données/fichier de configuration
|
|
||||||
edit-wip : Modifier un fichier dans le serveur 'wip'
|
|
||||||
edit_www : Modifier un fichier dans le serveur 'www'
|
|
||||||
new : [domain] Créer un domaine ou le modifier via le formulaire
|
|
||||||
[sidebar, navbar, footer, metas] Créer ou remplacer le
|
|
||||||
fichier de configuration du module par le défaut
|
|
||||||
[filename] (sans .tyto) Créer un article dans le
|
|
||||||
dossier actuel
|
|
||||||
[sitemap], créer le plan du site (sitemap)
|
|
||||||
|
|
||||||
# Afficher un fichier (avec numéros de ligne)
|
|
||||||
show : Fichier source, module de configuration
|
|
||||||
show-db : Afficher une base de données/fichier de configuration
|
|
||||||
show-wip : Afficher un fichier dans le serveur 'wip'
|
|
||||||
show-www : Afficher un fichier dans le serveur 'www'
|
|
||||||
|
|
||||||
# Processus de création / Mise en ligne
|
|
||||||
check : Vérifier la validité d'un article au format tyto
|
|
||||||
wip : Créer une page HTML de l'article dans le serveur 'wip'
|
|
||||||
force-wip : [file], check, wip
|
|
||||||
preview : [module]/[file], ouvre le fichier 'wip' dans le navigateur par défaut
|
|
||||||
publish : Créer une page HTML de l'article dans le serveur 'www'
|
|
||||||
quick-pub : [file] , check, wip, publish
|
|
||||||
|
|
||||||
# [target] > Selon l'action [action]
|
|
||||||
# Traitement en masse
|
|
||||||
updated : Mise à jour des articles modifiés (déjà vérifiés)
|
|
||||||
again : Forcer TOUS les articles déjà vérifiés
|
|
||||||
added : [check] Vérifier tous les article .tyto dans le domaine
|
|
||||||
qui n'ont pas été déjà validés
|
|
||||||
[wip, publish] Créer les pages HTML des articles
|
|
||||||
qui ont été modifiés et vérifiés
|
|
||||||
|
|
||||||
# Mise en ligne du thème et des modules
|
|
||||||
template : - Recréer les modules HTML dans "template/"
|
|
||||||
- Copie tous les autres fichier du dossier wip/template/
|
|
||||||
|
|
||||||
# Domaine et fichier
|
|
||||||
domain : Créer un domain ou le modifier
|
|
||||||
[file] : URI du fichier (l'autocompletion est votre amie)
|
|
||||||
|
|
||||||
# Les modules
|
|
||||||
footer : Fichier de configuration du pied de page
|
|
||||||
metas : Fichier de configuration des balises HTML <meta>, <link>
|
|
||||||
navbar : Fichier de configuration du menu de navigation
|
|
||||||
sidebar : Fichier de configuration de la barre latérale
|
|
||||||
stats : Fichier de statistiques (serveur 'wip' ou 'www')
|
|
||||||
sitemap : Fichier sitemap.tyto/.html
|
|
||||||
|
|
||||||
# [option]
|
|
||||||
--static : Créer une page HTML entièrement statique
|
|
||||||
--no-mods : Avec [publish template], ne pas recréer les modules
|
|
||||||
"""
|
|
||||||
|
|
||||||
ex_helps = """# Exemples :
|
|
||||||
# Vérifier l'article dans le sous dossier (suivant l'emplacement)
|
|
||||||
$ tyto check mysubdir/index.tyto
|
|
||||||
|
|
||||||
# Créer ou remettre par défaut la barre latérale
|
|
||||||
$ tyto new sidebar
|
|
||||||
|
|
||||||
# Modifier la configuration du menu de navigation
|
|
||||||
$ tyto edit navbar
|
|
||||||
|
|
||||||
# Modifier doc/index.html dans le serveur 'www'
|
|
||||||
$ tyto edit-www doc/index.tyto
|
|
||||||
|
|
||||||
# Créer le fichier HTML de la barre latérale (serveur 'wip')
|
|
||||||
$ tyto wip sidebar
|
|
||||||
|
|
||||||
# Afficher le contenu du pied de page HTML dans le serveur 'wip'
|
|
||||||
$ tyto show-wip footer
|
|
||||||
|
|
||||||
# Créer le fichier de statistiques dans le serveur 'www'
|
|
||||||
$ tyto publish stats"""
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Tyto - Littérateur
|
||||||
|
|
||||||
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# XMPP: echolib (im@echolib.re)
|
||||||
|
#
|
||||||
|
# Description: English website translation file
|
||||||
|
# File: /var/lib/tyto/translations/logs_en.py
|
||||||
|
#
|
||||||
|
# How to translate:
|
||||||
|
# - create filename website_xx.py in /var/lib/tyto/translations/
|
||||||
|
# where xx are 2 first lang letters (es, for spanish...)
|
||||||
|
# - copy its contents and translate values
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Note: python file
|
||||||
|
|
||||||
|
sidebar_title = "Featured posts"
|
||||||
|
sitemap = "sitemap"
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# Tyto - Littérateur
|
||||||
|
|
||||||
|
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# XMPP: echolib (im@echolib.re)
|
||||||
|
#
|
||||||
|
# Description: Fichier français de traduction des sites web
|
||||||
|
# File: /var/lib/tyto/translations/website_fr.py
|
||||||
|
#
|
||||||
|
# Comment traduire :
|
||||||
|
# - créer un fichier nommé logs_xx.py dans /var/lib/tyto/translations/
|
||||||
|
# oû xx sont les 2 première lettres de la langue (es, pour espagnol...)
|
||||||
|
# - Copier ce contenu dedans, et traduire les variables
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Rappel: Fichier au format python
|
||||||
|
|
||||||
|
sidebar_title = "Articles recommandés"
|
||||||
|
sitemap = "Plan du site"
|
Loading…
Reference in New Issue