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
|
||||
|
||||
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
|
||||
- Repository:
|
||||
- Issues:
|
||||
- Changelog:
|
||||
- License:
|
||||
- Documentation:
|
||||
|
||||
## [0.10.6]
|
||||
## [1.9.0]
|
||||
|
||||
|
||||
|
||||
|
|
57
README.md
57
README.md
|
@ -1,53 +1,14 @@
|
|||
# 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
|
||||
# Very early IN dev code
|
||||
This program can ve tested but not at all usable. Lots of work to do...
|
||||
|
||||
## 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/
|
||||
# Commands
|
||||
```
|
||||
cd articles/
|
||||
tyto new index
|
||||
tyto edit index.tyto
|
||||
# Get commands list help
|
||||
tyto
|
||||
```
|
||||
|
||||
# Vérifier, prévisualiser un article
|
||||
```
|
||||
tyto check index.tyto
|
||||
tyto wip index.tyto
|
||||
```
|
||||
# Working on
|
||||
- Managing domain(s)
|
||||
- - needs more checks to be validated
|
||||
- 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
|
||||
# Version: 1.0.0
|
||||
# Version: 1.9.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.
|
||||
#
|
||||
# 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# 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: Main binary to execute
|
||||
# Description: Main binary to execute.
|
||||
# Import modules and start checking/using arguments
|
||||
# File: /usr/bin/tyto
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# Project files : 20
|
||||
# Project lines : 7508
|
||||
# Project comments : 1153
|
||||
# Project functions: 109
|
||||
# Project program : 5652
|
||||
# Project files :
|
||||
# Project lines :
|
||||
# Project comments :
|
||||
# Project functions:
|
||||
# Project program :
|
||||
#
|
||||
# file lines : 93
|
||||
# file comments : 33
|
||||
# file functions: 0
|
||||
# file program : 47
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
|
||||
#======#
|
||||
# MAIN #
|
||||
#======#=======================================================================
|
||||
import sys
|
||||
sys.path.insert(0, '/var/lib/tyto/program')
|
||||
|
||||
#====================#
|
||||
# MAIN #
|
||||
# Treat Arguments #
|
||||
#--------------------#
|
||||
import logs
|
||||
|
||||
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
|
||||
action = args.set_action()
|
||||
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)
|
||||
|
||||
args.start_process()
|
||||
|
|
|
@ -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,174 +1,102 @@
|
|||
#!/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.
|
||||
#
|
||||
# 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# 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 arguments from command line
|
||||
# Description: Manage arguments from command line
|
||||
# File: /var/lib/tyto/program/args.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines : 174
|
||||
# file comments : 29
|
||||
# file functions: 2
|
||||
# file program : 135
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
|
||||
import sys
|
||||
import langs, tyto, debug, help, new, check, userset, show
|
||||
|
||||
import os, sys
|
||||
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]
|
||||
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]
|
||||
except: option = ''
|
||||
|
||||
# Set action and target for binary
|
||||
def set_action():
|
||||
return(action)
|
||||
|
||||
def set_target():
|
||||
return(target)
|
||||
#==================#
|
||||
# Target arguments #
|
||||
#------------------#
|
||||
def get_target():
|
||||
global target
|
||||
try: target = sys.argv[2]
|
||||
except: 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
|
||||
# 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.
|
||||
#
|
||||
# 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# 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: 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
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines : 90
|
||||
# file comments : 28
|
||||
# file functions: 0
|
||||
# file program : 53
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
|
||||
|
||||
import locale, sys, os, importlib
|
||||
import dom
|
||||
import sys, locale, os
|
||||
import args, debug, domain
|
||||
|
||||
|
||||
try:
|
||||
site.yes
|
||||
trfs = "/var/lib/tyto/translations/"
|
||||
|
||||
except:
|
||||
# Import translation directory
|
||||
trans_dir = '/var/lib/tyto/translations'
|
||||
sys.path.insert(0, trans_dir)
|
||||
#==================================#
|
||||
# Check if translation file exists #
|
||||
# module: #
|
||||
# - "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
|
||||
|
||||
# Create yes array with all yes languages
|
||||
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
|
||||
|
||||
try:
|
||||
answer_yes
|
||||
set_logs
|
||||
except:
|
||||
answer_yes = (())
|
||||
for lang_file in os.listdir(trans_dir):
|
||||
if lang_file.startswith("site_") and lang_file.endswith(".py"):
|
||||
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
|
||||
try:
|
||||
lang_sys = locale.getdefaultlocale()[0].split('_')[0]
|
||||
os.path.exists('%s/logs_%s.py'%(trans_dir, lang_sys))
|
||||
except:
|
||||
lang_sys = 'en'
|
||||
|
||||
|
||||
# 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)
|
||||
logs = __import__("logs_%s"%get_sys_lang())
|
||||
debug.out(201, lang, tr_logs_uri, False, 0, False)
|
||||
set_logs = True
|
||||
|
||||
|
||||
#=============================================================================#
|
||||
# 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:
|
||||
set_site
|
||||
except:
|
||||
site = __import__("website_%s"%get_website_lang())
|
||||
debug.out(208, site_lang, tr_website_uri, False, 0, False)
|
||||
set_site = True
|
||||
|
|
|
@ -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
|
||||
# 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.
|
||||
#
|
||||
# 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# 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: Create something new (domain, sidebar...)
|
||||
# Description: When user wants to create something new
|
||||
# File: /var/lib/tyto/program/new.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines : 94
|
||||
# file comments : 27
|
||||
# file functions: 1
|
||||
# file program : 59
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
|
||||
|
||||
import sys
|
||||
from unidecode import unidecode
|
||||
import args, dom, logs, langs, form, html, tyto, show, creators
|
||||
import args, domain
|
||||
|
||||
|
||||
#===============================================#
|
||||
# manage argument new for #
|
||||
# - domain: target becomes 3rd command argument #
|
||||
#-----------------------------------------------#
|
||||
def manage(target):
|
||||
# "domain" target
|
||||
#----------------
|
||||
option = args.action
|
||||
if target == "domain":
|
||||
try: option = sys.argv[3]
|
||||
except: option = args.action
|
||||
#====================================#
|
||||
# Manage arguments from command line #
|
||||
# Specific to action "new" #
|
||||
#------------------------------------#
|
||||
def manage(action, target):
|
||||
do = {
|
||||
"domain" : create_domain,
|
||||
}
|
||||
|
||||
if target in args.pass_targets:
|
||||
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")
|
||||
# args.target = unidecode(u)
|
||||
|
||||
filepost = "%s%s.tyto"%(dom.articles_d, args.target)
|
||||
if tyto.exists(filepost):
|
||||
logs.out("81", filepost, True)
|
||||
do[target]()
|
||||
|
||||
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)
|
||||
|
||||
|
||||
#===================================#
|
||||
# From command line "new domain" #
|
||||
# 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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
# 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.
|
||||
#
|
||||
# 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# 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 show*/edit* arguments.
|
||||
# Read or edit file from [target] argument
|
||||
# Description: When user wants to see something
|
||||
# File: /var/lib/tyto/program/show.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines : 216
|
||||
# file comments : 39
|
||||
# file functions: 3
|
||||
# file program : 156
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
|
||||
|
||||
import os, sys, importlib, subprocess
|
||||
import args, logs, langs, dom, db, form, tyto, check, html, stats
|
||||
import os
|
||||
import domain, debug
|
||||
|
||||
|
||||
#========================#
|
||||
# Read lines from a file #
|
||||
# alone: True/False #
|
||||
#------------------------#
|
||||
def read_lines(f, alone):
|
||||
if not f: return
|
||||
if not tyto.exists(f): logs.out("1", f, True)
|
||||
|
||||
datas = open(f).read()
|
||||
|
||||
# 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()
|
||||
#====================================#
|
||||
# Manage arguments from command line #
|
||||
# Specific to action "show" #
|
||||
#------------------------------------#
|
||||
def manage(action, target):
|
||||
do = {
|
||||
"domains": all_domains,
|
||||
}
|
||||
|
||||
do[target]()
|
||||
|
||||
|
||||
#======================#
|
||||
# From command line: #
|
||||
# Show or edit file #
|
||||
# final html, db, src #
|
||||
#----------------------#
|
||||
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):
|
||||
#============================#
|
||||
# List all registred domains #
|
||||
#----------------------------#
|
||||
def all_domains():
|
||||
domain.ult_dlf_load()
|
||||
try:
|
||||
xdg = subprocess.run(
|
||||
[
|
||||
'/usr/bin/xdg-open',
|
||||
file,
|
||||
],
|
||||
)
|
||||
except:
|
||||
logs.out("28", "/usr/bin/xdg-open %s"%file, True)
|
||||
c = 0
|
||||
for key, value in domain.ult_dlf.items("DOMAINS"):
|
||||
if key: c += 1
|
||||
print(": %s > %s"%(key,value))
|
||||
print("|\n; total =",c)
|
||||
|
||||
except:
|
||||
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
|
||||
# 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.
|
||||
#
|
||||
# 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# 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 and some seetings.
|
||||
# Description: Templates, settings, values
|
||||
# File: /var/lib/tyto/program/tyto.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines : 725
|
||||
# file comments : 121
|
||||
# file functions: 14
|
||||
# file program : 522
|
||||
#--------------------------
|
||||
#
|
||||
# Arguments in command line #
|
||||
#
|
||||
actions = (
|
||||
"check", "wip", "publish",
|
||||
"new",
|
||||
"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'
|
||||
Tytogit = 'https://git.a-lec.org/echolib/tyto-litterateur'
|
||||
Tytoweb = 'https://tyto.echolib.re'
|
||||
#===========================#
|
||||
# Templates #==================================================
|
||||
# Domain configuration file #
|
||||
#---------------------------#
|
||||
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
|
||||
needed_header_tags = \
|
||||
(
|
||||
'title',
|
||||
'about',
|
||||
'author',
|
||||
'tags',
|
||||
'date'
|
||||
)
|
||||
[WEBSITE_MODULES]
|
||||
navbar = yes
|
||||
sidebar_title =
|
||||
sidebar_items = 6
|
||||
sitemaps = yes
|
||||
rss_items = 100
|
||||
|
||||
# Optional header tags
|
||||
opt_header_tags = \
|
||||
(
|
||||
'file',
|
||||
'image',
|
||||
'link',
|
||||
'abbr',
|
||||
'raw',
|
||||
'code',
|
||||
'snpic'
|
||||
)
|
||||
[TEMPLATE_FILENAMES]
|
||||
favicon = favicon.png
|
||||
logo = logo.png
|
||||
styles = styles.css
|
||||
rss = rss.xml
|
||||
stats = stats.ini
|
||||
|
||||
opt_tags_long_name = \
|
||||
(
|
||||
'link',
|
||||
'file'
|
||||
)
|
||||
[USER_DIRS]
|
||||
root =
|
||||
articles =
|
||||
images =
|
||||
files =
|
||||
modules =
|
||||
database =
|
||||
template =
|
||||
|
||||
opt_tags_check_uri = \
|
||||
(
|
||||
'image',
|
||||
'file',
|
||||
'raw',
|
||||
'code'
|
||||
)
|
||||
[USER_TEMPLATE_FILES]
|
||||
logo =
|
||||
favicon =
|
||||
styles =
|
||||
|
||||
# Set all tags used in article's header
|
||||
headers = \
|
||||
(
|
||||
'title:',
|
||||
'about:',
|
||||
'author:',
|
||||
'tags:',
|
||||
'date:',
|
||||
'link:',
|
||||
'image:',
|
||||
'file:',
|
||||
'abbr:',
|
||||
'code:',
|
||||
'raw:',
|
||||
'#',
|
||||
'snpic:',
|
||||
)
|
||||
[USER_MODULES_FILES]
|
||||
metas =
|
||||
header =
|
||||
navbar =
|
||||
sidebar =
|
||||
footer =
|
||||
|
||||
[SERVER]
|
||||
root = /var/www/
|
||||
domain =
|
||||
|
||||
# Words Tags (paragraphs, lists, bold, strong...)
|
||||
# Used to check, and replace (wip) tags
|
||||
# ! As base64 is used, do NOT set marker: =_ _=
|
||||
# [5] = name for stats and log.
|
||||
#-------------------------------------------------------------
|
||||
icode_tags = \
|
||||
(
|
||||
'{_', '_}',
|
||||
'<code class="icode">', '</code>',
|
||||
'icodes',
|
||||
'\\{_', '\\_}'
|
||||
)
|
||||
|
||||
strong_tags = \
|
||||
(
|
||||
'*_', '_*',
|
||||
'<strong class="%s">'%dom.css, '</strong>',
|
||||
'strongs',
|
||||
'\\*_', '\\_*',
|
||||
'-S1-', '-S2-'
|
||||
)
|
||||
|
||||
bold_tags = \
|
||||
(
|
||||
'+_', '_+',
|
||||
'<b class="%s">'%dom.css, '</b>',
|
||||
'bolds',
|
||||
'\\+_', '\\_+',
|
||||
'-B1-', '-B2-'
|
||||
)
|
||||
|
||||
em_tags = \
|
||||
(
|
||||
';_', '_;',
|
||||
'<em class="%s">'%dom.css, '</em>',
|
||||
'emphasis',
|
||||
'\\;_', '\\_;',
|
||||
'-EM1-', '-EM2-'
|
||||
)
|
||||
|
||||
i_tags = \
|
||||
(
|
||||
':_', '_:',
|
||||
'<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-'
|
||||
)
|
||||
[WIP_DIRS]
|
||||
root =
|
||||
images =
|
||||
files =
|
||||
template =
|
||||
|
||||
markers_tags = \
|
||||
[
|
||||
strong_tags,
|
||||
bold_tags,
|
||||
em_tags,
|
||||
i_tags,
|
||||
u_tags,
|
||||
del_tags,
|
||||
cite_tags,
|
||||
custom1_tags,
|
||||
]
|
||||
[WIP_FILES]
|
||||
favicon =
|
||||
logo =
|
||||
styles =
|
||||
rss =
|
||||
stats =
|
||||
metas =
|
||||
header =
|
||||
navbar =
|
||||
sidebar =
|
||||
footer =
|
||||
|
||||
# At begining line, create block contents
|
||||
block_tags = [
|
||||
('((', '))', '<p class="%s">', '</p>', 'paragraphs'),
|
||||
('[[', ']]', '[[', ']]', 'quotes'),
|
||||
('{{', '}}', '{{', '}}', 'bcodes'),
|
||||
('-(', '-)', '-(', '-)', 'lists'),
|
||||
('<<', '>>', '<div class="%s">', '</div>', 'div'),
|
||||
]
|
||||
[WWW_DIRS]
|
||||
root =
|
||||
images =
|
||||
files =
|
||||
template =
|
||||
|
||||
# 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
|
||||
((
|
||||
|
||||
))
|
||||
[WWW_FILES]
|
||||
favicon =
|
||||
logo =
|
||||
styles =
|
||||
rss =
|
||||
stats =
|
||||
metas =
|
||||
header =
|
||||
navbar =
|
||||
sidebar =
|
||||
footer =
|
||||
|
||||
[TYTO]
|
||||
domain_hash =
|
||||
domain_conf =
|
||||
domain_user =
|
||||
"""
|
||||
|
||||
# Stats for icodes, bcodes, quotes
|
||||
nbr_icodes = 0
|
||||
|
||||
|
||||
#=======#
|
||||
# TOOLS #
|
||||
#=======#--------------------------------------------------------------
|
||||
# Template file configuration for each a created domain
|
||||
#
|
||||
# Return True if file exists
|
||||
#
|
||||
def exists(uri):
|
||||
if os.path.exists(uri): return(True)
|
||||
else: return(False)
|
||||
ini_domain_user = """[DOMAIN]
|
||||
name =
|
||||
hash =
|
||||
root =
|
||||
conf =
|
||||
|
||||
[SERVER]
|
||||
root =
|
||||
"""
|
||||
|
||||
#========================================#
|
||||
# Return converted valid HTML characters #
|
||||
#----------------------------------------#
|
||||
def convert_altname(altname):
|
||||
altname = altname.replace('<', '<')
|
||||
altname = altname.replace('>', '>')
|
||||
altname = altname.replace('"', '"')
|
||||
altname = altname.replace("'", ''')
|
||||
ini_domains_list = """[DOMAINS]
|
||||
"""
|
||||
|
||||
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
|
||||
# Name: 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
|
||||
# Tyto - Littérateur
|
||||
|
||||
#**********************************************************************
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
||||
# Generic
|
||||
sidebar = 'Sidebar'
|
||||
navbar = 'Navbar'
|
||||
meta_t = '<meta> tag'
|
||||
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"
|
||||
# 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.
|
||||
|
||||
file_c = "File created"
|
||||
file_n = "File changed"
|
||||
file_e = "File exists"
|
||||
dir_c = "Directory created"
|
||||
dir_e = "Directory exists"
|
||||
post_exists = "Ab article already exists"
|
||||
# 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.
|
||||
|
||||
# chk
|
||||
shebang_r= 'Remove shebang'
|
||||
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"
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
# wip
|
||||
nywip = "Article not yet wip"
|
||||
was_wip = "Article was 'wip'"
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# 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
|
||||
was_pub = "Article was published"
|
||||
# Note: python file
|
||||
|
||||
# Misc
|
||||
post_nfd = "Page not found"
|
||||
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'"
|
||||
# Réponses valides (! NON sensible à la case : oui = OUI, Oui...)
|
||||
ok = ("yes", "y")
|
||||
|
||||
|
||||
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
|
||||
# Nom: 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
|
||||
# Tyto - Littérateur
|
||||
|
||||
#**********************************************************************
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
||||
# Generique
|
||||
sidebar = 'Barre Latérale'
|
||||
navbar = 'Barre de navigation'
|
||||
meta_t = 'Balise <meta>'
|
||||
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à"
|
||||
# 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.
|
||||
|
||||
# chk
|
||||
shebang_r= 'Enlever le shebang'
|
||||
nycheck = "Article pas encore 'check'"
|
||||
was_chk = "Article déjà vérifié"
|
||||
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"
|
||||
# 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.
|
||||
|
||||
# Wip
|
||||
nywip = "Article pas encore 'wip'"
|
||||
was_wip = "Article déjà 'wip'"
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
# 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
|
||||
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"
|
||||
# Rappel: Fichier au format python
|
||||
|
||||
static_n = "Page non statique"
|
||||
check_m = "Vérifier manuellement"
|
||||
post_chg = "Article modifié : commencer par 'check'"
|
||||
sep_inv = "Séparateur manquant dans l'article"
|
||||
unused_v = "Valeur manquante dans l'article"
|
||||
unused_t = "Valeur manquante dans l'entête"
|
||||
mark_np = "Marqueurs non jumelés"
|
||||
symb_np = "Symboles non jumelés"
|
||||
snpic_d = "snpic utilisé par défaut. Manquant"
|
||||
anch_nu = "Ancre non unique"
|
||||
nyfile = "Fichier pas encore créé"
|
||||
# Réponses valides (! NON sensible à la case : oui = OUI, Oui...)
|
||||
ok = ("oui", "o")
|
||||
|
||||
# Form
|
||||
q = " ?"
|
||||
configure_domain = "Configurer le domaine"
|
||||
domain_title = "Titre du domaine"
|
||||
domain_date = "Date de création"
|
||||
domain_about = "Description du domaine"
|
||||
domain_mail = "Courriel de l'administration"
|
||||
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