Ménage d'hiver partie 2
This commit is contained in:
parent
b9bd5ab1fc
commit
bb0bedf1fd
9 changed files with 204 additions and 205 deletions
|
@ -1,37 +0,0 @@
|
|||
# Makefile
|
||||
# --------
|
||||
# Copyright : (c) 2008, Jeremie Dimino <dimino@crans.org>
|
||||
# Licence : BSD3
|
||||
|
||||
# Notes:
|
||||
#
|
||||
# Il faut créer un lien de ce fichier depuis le /usr/scripts vers le
|
||||
# dossier contenant les paquets du crans (/puftp/custom) sur la
|
||||
# machine avec le ftp (ftp.crans.org)
|
||||
|
||||
.PHONY: all Packages Sources clean
|
||||
|
||||
all: Release Release.gpg
|
||||
|
||||
Release: Packages Packages.gz Packages.bz2 Sources Sources.gz Sources.bz2
|
||||
apt-ftparchive -o "APT::FTPArchive::Release::Suite=crans" release . > Release
|
||||
|
||||
Release.gpg: Release
|
||||
rm -f Release.gpg
|
||||
@echo "*** Pensez à exécuter la commande suivante sur une machine avec votre clef gpg ***"
|
||||
gpg -asbo Release.gpg Release
|
||||
|
||||
Packages:
|
||||
apt-ftparchive packages . > Packages
|
||||
|
||||
Sources:
|
||||
apt-ftparchive sources . > Sources
|
||||
|
||||
%.gz: %
|
||||
gzip -c $< > $@
|
||||
|
||||
%.bz2: %
|
||||
bzip2 -c $< > $@
|
||||
|
||||
clean:
|
||||
rm -f Packages Packages.gz Packages.bz2 Sources Sources.gz Sources.bz2 Release Release.gpg
|
|
@ -1,89 +0,0 @@
|
|||
#! /bin/bash
|
||||
# Mettre cette variable à 1 si on veut que le corbeau soit actif.
|
||||
ACTIF=0
|
||||
|
||||
TEMP="$(mktemp)"
|
||||
trap "rm -f ${TEMP}" EXIT
|
||||
|
||||
# On désactive spamassassin car il semble y avoir des problèmes
|
||||
# (de toute façon, c'est pas super utile vu l'autre vérification)
|
||||
# spamassassin -e -p /etc/spamassassin/corbeau.conf > ${TEMP}
|
||||
|
||||
cat > ${TEMP}
|
||||
|
||||
# Est-ce que le corbeau est actif ?
|
||||
if [[ $ACTIF == 1 ]]; then
|
||||
|
||||
# Est-ce du spam ?
|
||||
if [[ $? == 0 ]]; then
|
||||
|
||||
# Est-ce que ça contient le mot de passe ?
|
||||
if cat ${TEMP} | egrep -q "^Mot de passe : corbeau$"; then
|
||||
# On loggue tout dans /var/log/corbeau
|
||||
DIR="/var/log/corbeau"
|
||||
FILE="corbeau_$(date +%Y_%m_%d_%H_%M_%S)";
|
||||
|
||||
# Création d'une clef AES aléatoire de 256 bits.
|
||||
dd if=/dev/urandom bs=32 count=1 | sha256sum | head -c 32 >> ${DIR}/keys/${FILE}.key 2>> /var/log/corbeau/corbeau.err
|
||||
|
||||
# Chiffrement du mail venant vers corbeau@crans.org à l'aide de la clef
|
||||
cat ${TEMP} | gpg --armour --symmetric --cipher-algo aes256 --passphrase $(cat ${DIR}/keys/${FILE}.key) >> ${DIR}/${FILE}.log 2>> /var/log/corbeau/corbeau.err
|
||||
|
||||
# Cf ssss, l'idée est de finir par splitter la clef AES à l'aide de ssss-split, et d'en distribuer un bout à chaque membre du C.A., il faudrait au minimum #ca/2 bouts de la clef pour la reconstruire, et débaguer le corbeau.
|
||||
|
||||
# Puis on envoit la version modifiée.
|
||||
cat ${TEMP} | egrep -v "^Mot de passe : corbeau$" | \
|
||||
formail -I "Received" \
|
||||
-I "From" \
|
||||
-I "Sender" \
|
||||
-I "DKIM-Signature" \
|
||||
-I "DomainKey-Signature" \
|
||||
-I "X-Google-Sender-Auth" \
|
||||
-I "X-Original-To" \
|
||||
-I "X-Virus-Scanned" \
|
||||
-I "X-Greylist" \
|
||||
-I "Delivered-To" \
|
||||
-I "To" \
|
||||
-I "Message-ID" \
|
||||
-I "User-Agent" \
|
||||
-I "X-Newsreader" \
|
||||
-I "Organization" \
|
||||
-I "Return-Path" \
|
||||
-A "Message-Id: $(date '+<corbeau.%s@crans.org>')" \
|
||||
-A "From: corbeau@crans.org" \
|
||||
-A "Newsgroups: crans.radio-ragots" \
|
||||
-A "Path: Corbeau" | \
|
||||
rnews 2>> /var/log/corbeau/corbeau.err
|
||||
|
||||
# Le mail ne contient pas le mot de passe, on répond à l'expéditeur
|
||||
else
|
||||
( cat ${TEMP} | formail -r -A "From: corbeau@crans.org" -A "Content-Type: text/plain; charset=UTF-8; format=flowed" ; cat << EOF
|
||||
Bonjour,
|
||||
|
||||
Ton mail n'est pas valide car il manque la ligne suivante :
|
||||
"Mot de passe : corbeau"
|
||||
|
||||
Pour plus d'informations :
|
||||
http://wiki.crans.org/VieCrans/ForumNews/LeCorbeau
|
||||
|
||||
--
|
||||
Le corbeau
|
||||
EOF
|
||||
) | /usr/sbin/sendmail -t
|
||||
fi
|
||||
fi
|
||||
|
||||
# Corbal inactif, on répond à l'expéditeur.
|
||||
else
|
||||
( cat ${TEMP} | formail -r -A "From: corbeau@crans.org" -A "Content-Type: text/plain; charset=UTF-8; format=flowed" ; cat << EOF
|
||||
Bonjour,
|
||||
|
||||
Le corbeau est actuellement désactivé. Il est donc inutile d'essayer de t'en servir.
|
||||
|
||||
En te remerciant de ta compréhension,
|
||||
|
||||
--
|
||||
Le corbeau, désactivé.
|
||||
EOF
|
||||
) | /usr/sbin/sendmail -t
|
||||
fi
|
|
@ -1,83 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
class PagePerso:
|
||||
"""Classe représentant la page perso d'une personne"""
|
||||
|
||||
home = "/home"
|
||||
www = "/www"
|
||||
|
||||
def __init__(self, login):
|
||||
"""Instanciation avec le login' de la personne"""
|
||||
self.login = login
|
||||
self.home = "%s/%s" % (self.home, login)
|
||||
_info = {}
|
||||
self._load_informations()
|
||||
|
||||
def _filename( self ):
|
||||
return "%s/.info" % self.home
|
||||
|
||||
def _load_informations(self):
|
||||
try:
|
||||
lignes = file( self._filename() )
|
||||
except IOError:
|
||||
lignes = []
|
||||
# self._info est un dictionnaire qui reprend le contenu du .info
|
||||
self._info = dict( map( lambda z: (unicode(z[0].lower(),"iso-8859-15"),
|
||||
unicode(z[1],"iso-8859-15")),
|
||||
filter(lambda w: len(w) == 2 and len(w[1]),
|
||||
map(lambda x: map(lambda y: y.strip(),
|
||||
x.split(":")),
|
||||
lignes))))
|
||||
|
||||
def _save_informations( self ):
|
||||
myfile = file(self._filename(), "w")
|
||||
for aKey in self._info.keys():
|
||||
myfile.write("%s:%s\n" % (aKey, self.
|
||||
_info[aKey]) )
|
||||
myfile.write("\n")
|
||||
|
||||
def save( self ):
|
||||
self._save_informations()
|
||||
|
||||
def chemin(self):
|
||||
"""Chemin vers le www"""
|
||||
return u"%s%s" % (self.home, self.www)
|
||||
|
||||
def url(self):
|
||||
"""URL vers la page perso"""
|
||||
return u"http://perso.crans.org/%s/" % self.login
|
||||
|
||||
def nom( self ):
|
||||
return self._info.get("nom", "")
|
||||
|
||||
def setNom( self, nom ):
|
||||
self._info["nom"] = nom
|
||||
|
||||
def slogan( self ):
|
||||
return self._info.get("slogan", "")
|
||||
|
||||
def setSlogan( self, slogan ):
|
||||
self._info["slogan"] = slogan
|
||||
|
||||
def logo(self):
|
||||
"""URL du logo s'il y en a un"""
|
||||
logo = self._info.get("logo", None)
|
||||
if logo:
|
||||
# Le logo peut être en absolu ou en relatif
|
||||
if logo.startswith(self.chemin()):
|
||||
logo = logo.replace("%s/" % self.chemin(), "")
|
||||
if os.path.isfile("%s/%s" % (self.chemin(), logo)):
|
||||
return u"%s%s" % (self.url(), logo)
|
||||
return u"http://perso.crans.org/pageperso.png"
|
||||
|
||||
def __str__(self):
|
||||
"""Renvoie le code HTML correspondant au fichier .info"""
|
||||
html = [ u'<div class="vignetteperso">',
|
||||
u'<a href="%s">' % self.url(),
|
||||
u'<img src="%s" alt="%s">' % (self.logo(), self.login),
|
||||
u'</a><br>',
|
||||
self.info("nom") and u'<b>%s</b><br>' % self.info("nom") or u'%s<br>' % self.login,
|
||||
self.info("devise") and u'<i>%s</i>' % self.info("devise") or u'',
|
||||
u'</div>' ]
|
||||
return u'\n'.join(html)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
sudo -u respbats /usr/scripts/impression/recredit.py "$@"
|
|
@ -1,49 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# run-bcfg2.sh
|
||||
# ------------
|
||||
# Copyright : (c) 2008, Jeremie Dimino <jeremie@dimino.org>
|
||||
# Licence : BSD3
|
||||
|
||||
# Script pour lancer bcfg2 -v -I sur tous les serveurs.
|
||||
#
|
||||
# Pour l'utiliser vous devez le copier sur votre ordi, et le lancer
|
||||
# avec en argument une liste de serveurs:
|
||||
#
|
||||
# $ ./run-bcfg2.sh rouge zamok
|
||||
#
|
||||
# Sans aucun serveur il récupère la liste de tous les serveurs depuis
|
||||
# la conf de bcfg2.
|
||||
|
||||
# Pour que ça marche il faut que vous puissiez vous connecter aux
|
||||
# serveurs sans mot de passe et que vous aiyez déjà accepté la clef
|
||||
# pour chaque serveur
|
||||
|
||||
# Liste des machines à contacter
|
||||
if [ $# = 0 ]; then
|
||||
echo "Récupération de la liste des machines depuis la conf de bcfg2..."
|
||||
HOSTS=$(ssh vert.adm.crans.org grep -o "'name=\"[^\"]*\"'" /var/lib/bcfg2/Metadata/clients.xml | cut -d'"' -f2)
|
||||
else
|
||||
HOSTS="$@"
|
||||
fi
|
||||
|
||||
echo "Veuillez taper votre mot de passe du crans:"
|
||||
read -s -p "password: " password
|
||||
echo
|
||||
|
||||
echo "Obtention des tokens pour sudo..."
|
||||
pids=""
|
||||
for host in $HOSTS; do
|
||||
echo $password | ssh $host sudo -S true & pids="$pids $!"
|
||||
done
|
||||
|
||||
# On attend que tous les sudo soient terminés
|
||||
for pid in $pids; do
|
||||
wait $pid
|
||||
done
|
||||
|
||||
echo "Lancement de bcfg2 sur tous les serveurs"
|
||||
for host in $HOSTS; do
|
||||
echo " $host"
|
||||
x-terminal-emulator -title $host -e ssh -t $host sudo bcfg2 -v -I &
|
||||
done
|
|
@ -1 +0,0 @@
|
|||
stats_cableurs2.py
|
204
utils/stats_cableurs.py
Executable file
204
utils/stats_cableurs.py
Executable file
|
@ -0,0 +1,204 @@
|
|||
#!/bin/bash /usr/scripts/python.sh
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# stats_cableurs.py
|
||||
# -----------------
|
||||
#
|
||||
# Copyright (C) 2013-2015 Raphaël-David Lasseri <lasseri@crans.org>,
|
||||
# Pierre-Elliott Bécue <becue@crans.org>,
|
||||
#
|
||||
# This file 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 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This file 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, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
|
||||
"""
|
||||
Ce script permet de se faire mousser en listant les câbleurs et leurs
|
||||
stats.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import datetime
|
||||
import argparse
|
||||
|
||||
import lc_ldap.shortcuts as shortcuts
|
||||
import lc_ldap.crans_utils as crans_utils
|
||||
import gestion.config as config
|
||||
import gestion.affichage as affichage
|
||||
|
||||
from cranslib.decorators import static_var
|
||||
from config import ann_scol
|
||||
|
||||
|
||||
### Appels à LDAP et tri initial sur l'année en cours.
|
||||
DB = shortcuts.lc_ldap_readonly()
|
||||
SCORES = []
|
||||
HISTORIQUE = []
|
||||
ENCODING = config.out_encoding
|
||||
|
||||
@static_var(("data", []))
|
||||
def adherents(regen=False):
|
||||
"""Fonction évaluée paresseusement pour retourner la liste des
|
||||
adhérents"""
|
||||
|
||||
if regen or not adherents.data:
|
||||
adherents.data = DB.search(u'(&(debutAdhesion>=%s)(aid=*))' % (config.gtf_debut_periode_transitoire,), sizelimit=2000)
|
||||
return list(adherents.data)
|
||||
|
||||
@static_var(("data", []))
|
||||
def factures(regen=False):
|
||||
"""Fonction évaluée paresseusement pour retourner la liste des factures"""
|
||||
|
||||
if regen or not factures.data:
|
||||
factures.data = DB.search(u'(&(|(debutAdhesion>=%(now)s)(debutConnexion>=%(now)s))(fid=*))' % {
|
||||
'now': config.gtf_debut_periode_transitoire,
|
||||
}, sizelimit=0)
|
||||
return list(factures.data)
|
||||
|
||||
@static_var(("data", []))
|
||||
def cableurs(regen=False):
|
||||
"""Fonction évaluée paresseusement pour retourner la liste des
|
||||
câbleurs"""
|
||||
|
||||
if regen or not cableurs.data:
|
||||
cableurs.data = DB.search(u'(|(droits=cableur)(droits=nounou)(droits=bureau))')
|
||||
return list(cableurs.data)
|
||||
|
||||
#### On prends les historiques de tout les adhérents
|
||||
def parse_historique(ligne):
|
||||
"""Parse une ligne d'historique et renvoie [ligne parsée],action
|
||||
du cableur, date de l'action"""
|
||||
champ = ligne.value.replace(',', '').replace(':', '').split(' ', 3)
|
||||
sdate = champ[0].split('/')
|
||||
date = datetime.date(int(sdate[2]), int(sdate[1]), int(sdate[0]))
|
||||
champ_action = champ[3]
|
||||
return (champ, champ_action, date)
|
||||
|
||||
def actions_cableurs():
|
||||
"""Renvoie l'historique de tous les adherents et tri en fonction
|
||||
des actions éffectuées."""
|
||||
for adherent in adherents():
|
||||
histo = adherent.get('historique', [])
|
||||
for histo_line in histo:
|
||||
champ = parse_historique(histo_line)[0]
|
||||
champ_action = parse_historique(histo_line)[1]
|
||||
date = parse_historique(histo_line)[2]
|
||||
if (u' inscription' in champ_action or u'Adhesion+' in champ_action) and date > datetime.date(ann_scol, 8, 1):
|
||||
HISTORIQUE.append(champ)
|
||||
|
||||
for facture in factures():
|
||||
histo = facture.get('historique', [])
|
||||
for histo_line in histo:
|
||||
champ = parse_historique(histo_line)[0]
|
||||
champ_action = parse_historique(histo_line)[1]
|
||||
date = parse_historique(histo_line)[2]
|
||||
if u'controle' in champ_action and date > datetime.date(ann_scol, 8, 1):
|
||||
HISTORIQUE.append(champ)
|
||||
return HISTORIQUE
|
||||
|
||||
#### On parse l'historique et on trie
|
||||
def score_cableurs():
|
||||
"""Calcul le score de tout les câbleurs en fonction des actions
|
||||
effectuées """
|
||||
for cableur in cableurs():
|
||||
inscriptions = reinscriptions = controles = 0
|
||||
nom = cableur.get(u'nom', None)[0].value
|
||||
prenom = cableur.get(u'prenom', None)[0].value
|
||||
uid = cableur.get(u'uid', None)[0].value
|
||||
for index in range (0, len(HISTORIQUE)):
|
||||
histo_uid = HISTORIQUE[index][2]
|
||||
histo_action = HISTORIQUE[index][3]
|
||||
if histo_uid == uid and histo_action == u' inscription':
|
||||
inscriptions += 1
|
||||
if histo_uid == uid and (u"debutAdhesion+" in histo_action):
|
||||
reinscriptions += 1
|
||||
if histo_uid == uid and (u"controle" in histo_action):
|
||||
controles += 1
|
||||
score = 2*inscriptions + reinscriptions + controles
|
||||
SCORES.append(["%s %s" % (prenom, nom), score, inscriptions, reinscriptions, controles])
|
||||
return SCORES
|
||||
|
||||
### Tri par score
|
||||
def sort_by_score():
|
||||
"""Tri la liste des câbleurs par ordre de score décroissant de score"""
|
||||
return score_cableurs().sort(key=lambda x:int(x[1]), reverse=True)
|
||||
|
||||
def sort_by_inverse_score():
|
||||
"""Tri la liste des câbleurs par ordre de score croissant de score"""
|
||||
return score_cableurs().sort(key=lambda x:int(x[1]))
|
||||
|
||||
def cableurs_utiles():
|
||||
"""Renvoi le nombre de cableurs ayant un score non nul"""
|
||||
useless_cableurs = 0
|
||||
for k in range(0, len(cableurs())):
|
||||
if (SCORES[k][1] == 0):
|
||||
useless_cableurs = useless_cableurs + 1
|
||||
return len(cableurs()) - useless_cableurs
|
||||
|
||||
|
||||
#### Affichage ou x est le nombre de câbleurs à afficher
|
||||
def show_all(limit, swap):
|
||||
"""Tableau fait main pour un effet plus visuel"""
|
||||
titre = [u"Câbleur", u"Score", u"Inscriptions", u"Réinscriptions", u"Contrôles"]
|
||||
largeur = [25, 8, 16, 16, 16]
|
||||
alignement = ["c", "c", "c", "c", "c"]
|
||||
data = [[elem for elem in SCORES[index]] for index in xrange(limit)]
|
||||
total = [0]*4
|
||||
for elem in SCORES:
|
||||
total = [total[i] + elem[i+1] for i in xrange(len(total))]
|
||||
total = [["Total"] + total]
|
||||
print affichage.tableau(data, titre=titre, largeur=largeur, alignement=alignement, swap=swap).encode(ENCODING)
|
||||
print affichage.tableau(total, titre=titre, largeur=largeur, alignement=alignement, swap=swap).encode(ENCODING)
|
||||
|
||||
#### On définit le Parser
|
||||
if __name__ == "__main__":
|
||||
actions_cableurs()
|
||||
|
||||
PARSER = argparse.ArgumentParser()
|
||||
PARSER.add_argument("-a", "--all", help="Affiche les scores de tout les câbleurs", action="store_true")
|
||||
PARSER.add_argument("-t", "--top", help="Affiche seulement les meilleurs câbleurs", action="store_true")
|
||||
PARSER.add_argument("-s", "--scores", help="Affiche seulement les câbleurs ayant un score non nul", action="store_true")
|
||||
PARSER.add_argument("-m", "--menage", help="Affiche seulement les câbleurs ayant un score nul", action="store_true")
|
||||
PARSER.add_argument("-n", "--nocolour", help="Désactive la couleur", action="store_true")
|
||||
ARGS = PARSER.parse_args()
|
||||
|
||||
|
||||
if ARGS.nocolour:
|
||||
SWAP = []
|
||||
else:
|
||||
SWAP = [None, "vert"]
|
||||
|
||||
if ARGS.all:
|
||||
sort_by_score()
|
||||
show_all(len(cableurs()), swap=SWAP)
|
||||
elif ARGS.scores:
|
||||
sort_by_score()
|
||||
show_all(cableurs_utiles(), swap=SWAP)
|
||||
elif ARGS.menage:
|
||||
sort_by_inverse_score()
|
||||
show_all(len(cableurs()) - cableurs_utiles(), swap=SWAP)
|
||||
elif ARGS.top:
|
||||
sort_by_score()
|
||||
show_all(5, swap=SWAP)
|
||||
else:
|
||||
sort_by_score()
|
||||
show_all(10, swap=SWAP)
|
||||
print affichage.style(u"""stats_cableurs n'est pas un jouet, ni un outil
|
||||
pour comparer qui de deux membres actifs a fait le plus de
|
||||
câblages. C'est un outil qui sert au conseil d'administration
|
||||
et aux nounous pour le suivi.
|
||||
|
||||
De plus, l'utiliser à tort et à travers occasionne de la charge
|
||||
sur la base de données des adhérents, que le script doit aller
|
||||
lire pour afficher les résultats.
|
||||
|
||||
Merci d'user de ce script avec parcimonie, et de ne pas jouer à
|
||||
"qui à la plus grosse".""", ['rouge']).encode(ENCODING)
|
|
@ -1,204 +0,0 @@
|
|||
#!/bin/bash /usr/scripts/python.sh
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# stats_cableurs.py
|
||||
# -----------------
|
||||
#
|
||||
# Copyright (C) 2013-2015 Raphaël-David Lasseri <lasseri@crans.org>,
|
||||
# Pierre-Elliott Bécue <becue@crans.org>,
|
||||
#
|
||||
# This file 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 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This file 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, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
|
||||
"""
|
||||
Ce script permet de se faire mousser en listant les câbleurs et leurs
|
||||
stats.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import datetime
|
||||
import argparse
|
||||
|
||||
import lc_ldap.shortcuts as shortcuts
|
||||
import lc_ldap.crans_utils as crans_utils
|
||||
import gestion.config as config
|
||||
import gestion.affichage as affichage
|
||||
|
||||
from cranslib.decorators import static_var
|
||||
from config import ann_scol
|
||||
|
||||
|
||||
### Appels à LDAP et tri initial sur l'année en cours.
|
||||
DB = shortcuts.lc_ldap_readonly()
|
||||
SCORES = []
|
||||
HISTORIQUE = []
|
||||
ENCODING = config.out_encoding
|
||||
|
||||
@static_var(("data", []))
|
||||
def adherents(regen=False):
|
||||
"""Fonction évaluée paresseusement pour retourner la liste des
|
||||
adhérents"""
|
||||
|
||||
if regen or not adherents.data:
|
||||
adherents.data = DB.search(u'(&(debutAdhesion>=%s)(aid=*))' % (config.gtf_debut_periode_transitoire,), sizelimit=2000)
|
||||
return list(adherents.data)
|
||||
|
||||
@static_var(("data", []))
|
||||
def factures(regen=False):
|
||||
"""Fonction évaluée paresseusement pour retourner la liste des factures"""
|
||||
|
||||
if regen or not factures.data:
|
||||
factures.data = DB.search(u'(&(|(debutAdhesion>=%(now)s)(debutConnexion>=%(now)s))(fid=*))' % {
|
||||
'now': config.gtf_debut_periode_transitoire,
|
||||
}, sizelimit=0)
|
||||
return list(factures.data)
|
||||
|
||||
@static_var(("data", []))
|
||||
def cableurs(regen=False):
|
||||
"""Fonction évaluée paresseusement pour retourner la liste des
|
||||
câbleurs"""
|
||||
|
||||
if regen or not cableurs.data:
|
||||
cableurs.data = DB.search(u'(|(droits=cableur)(droits=nounou)(droits=bureau))')
|
||||
return list(cableurs.data)
|
||||
|
||||
#### On prends les historiques de tout les adhérents
|
||||
def parse_historique(ligne):
|
||||
"""Parse une ligne d'historique et renvoie [ligne parsée],action
|
||||
du cableur, date de l'action"""
|
||||
champ = ligne.value.replace(',', '').replace(':', '').split(' ', 3)
|
||||
sdate = champ[0].split('/')
|
||||
date = datetime.date(int(sdate[2]), int(sdate[1]), int(sdate[0]))
|
||||
champ_action = champ[3]
|
||||
return (champ, champ_action, date)
|
||||
|
||||
def actions_cableurs():
|
||||
"""Renvoie l'historique de tous les adherents et tri en fonction
|
||||
des actions éffectuées."""
|
||||
for adherent in adherents():
|
||||
histo = adherent.get('historique', [])
|
||||
for histo_line in histo:
|
||||
champ = parse_historique(histo_line)[0]
|
||||
champ_action = parse_historique(histo_line)[1]
|
||||
date = parse_historique(histo_line)[2]
|
||||
if (u' inscription' in champ_action or u'Adhesion+' in champ_action) and date > datetime.date(ann_scol, 8, 1):
|
||||
HISTORIQUE.append(champ)
|
||||
|
||||
for facture in factures():
|
||||
histo = facture.get('historique', [])
|
||||
for histo_line in histo:
|
||||
champ = parse_historique(histo_line)[0]
|
||||
champ_action = parse_historique(histo_line)[1]
|
||||
date = parse_historique(histo_line)[2]
|
||||
if u'controle' in champ_action and date > datetime.date(ann_scol, 8, 1):
|
||||
HISTORIQUE.append(champ)
|
||||
return HISTORIQUE
|
||||
|
||||
#### On parse l'historique et on trie
|
||||
def score_cableurs():
|
||||
"""Calcul le score de tout les câbleurs en fonction des actions
|
||||
effectuées """
|
||||
for cableur in cableurs():
|
||||
inscriptions = reinscriptions = controles = 0
|
||||
nom = cableur.get(u'nom', None)[0].value
|
||||
prenom = cableur.get(u'prenom', None)[0].value
|
||||
uid = cableur.get(u'uid', None)[0].value
|
||||
for index in range (0, len(HISTORIQUE)):
|
||||
histo_uid = HISTORIQUE[index][2]
|
||||
histo_action = HISTORIQUE[index][3]
|
||||
if histo_uid == uid and histo_action == u' inscription':
|
||||
inscriptions += 1
|
||||
if histo_uid == uid and (u"debutAdhesion+" in histo_action):
|
||||
reinscriptions += 1
|
||||
if histo_uid == uid and (u"controle" in histo_action):
|
||||
controles += 1
|
||||
score = 2*inscriptions + reinscriptions + controles
|
||||
SCORES.append(["%s %s" % (prenom, nom), score, inscriptions, reinscriptions, controles])
|
||||
return SCORES
|
||||
|
||||
### Tri par score
|
||||
def sort_by_score():
|
||||
"""Tri la liste des câbleurs par ordre de score décroissant de score"""
|
||||
return score_cableurs().sort(key=lambda x:int(x[1]), reverse=True)
|
||||
|
||||
def sort_by_inverse_score():
|
||||
"""Tri la liste des câbleurs par ordre de score croissant de score"""
|
||||
return score_cableurs().sort(key=lambda x:int(x[1]))
|
||||
|
||||
def cableurs_utiles():
|
||||
"""Renvoi le nombre de cableurs ayant un score non nul"""
|
||||
useless_cableurs = 0
|
||||
for k in range(0, len(cableurs())):
|
||||
if (SCORES[k][1] == 0):
|
||||
useless_cableurs = useless_cableurs + 1
|
||||
return len(cableurs()) - useless_cableurs
|
||||
|
||||
|
||||
#### Affichage ou x est le nombre de câbleurs à afficher
|
||||
def show_all(limit, swap):
|
||||
"""Tableau fait main pour un effet plus visuel"""
|
||||
titre = [u"Câbleur", u"Score", u"Inscriptions", u"Réinscriptions", u"Contrôles"]
|
||||
largeur = [25, 8, 16, 16, 16]
|
||||
alignement = ["c", "c", "c", "c", "c"]
|
||||
data = [[elem for elem in SCORES[index]] for index in xrange(limit)]
|
||||
total = [0]*4
|
||||
for elem in SCORES:
|
||||
total = [total[i] + elem[i+1] for i in xrange(len(total))]
|
||||
total = [["Total"] + total]
|
||||
print affichage.tableau(data, titre=titre, largeur=largeur, alignement=alignement, swap=swap).encode(ENCODING)
|
||||
print affichage.tableau(total, titre=titre, largeur=largeur, alignement=alignement, swap=swap).encode(ENCODING)
|
||||
|
||||
#### On définit le Parser
|
||||
if __name__ == "__main__":
|
||||
actions_cableurs()
|
||||
|
||||
PARSER = argparse.ArgumentParser()
|
||||
PARSER.add_argument("-a", "--all", help="Affiche les scores de tout les câbleurs", action="store_true")
|
||||
PARSER.add_argument("-t", "--top", help="Affiche seulement les meilleurs câbleurs", action="store_true")
|
||||
PARSER.add_argument("-s", "--scores", help="Affiche seulement les câbleurs ayant un score non nul", action="store_true")
|
||||
PARSER.add_argument("-m", "--menage", help="Affiche seulement les câbleurs ayant un score nul", action="store_true")
|
||||
PARSER.add_argument("-n", "--nocolour", help="Désactive la couleur", action="store_true")
|
||||
ARGS = PARSER.parse_args()
|
||||
|
||||
|
||||
if ARGS.nocolour:
|
||||
SWAP = []
|
||||
else:
|
||||
SWAP = [None, "vert"]
|
||||
|
||||
if ARGS.all:
|
||||
sort_by_score()
|
||||
show_all(len(cableurs()), swap=SWAP)
|
||||
elif ARGS.scores:
|
||||
sort_by_score()
|
||||
show_all(cableurs_utiles(), swap=SWAP)
|
||||
elif ARGS.menage:
|
||||
sort_by_inverse_score()
|
||||
show_all(len(cableurs()) - cableurs_utiles(), swap=SWAP)
|
||||
elif ARGS.top:
|
||||
sort_by_score()
|
||||
show_all(5, swap=SWAP)
|
||||
else:
|
||||
sort_by_score()
|
||||
show_all(10, swap=SWAP)
|
||||
print affichage.style(u"""stats_cableurs n'est pas un jouet, ni un outil
|
||||
pour comparer qui de deux membres actifs a fait le plus de
|
||||
câblages. C'est un outil qui sert au conseil d'administration
|
||||
et aux nounous pour le suivi.
|
||||
|
||||
De plus, l'utiliser à tort et à travers occasionne de la charge
|
||||
sur la base de données des adhérents, que le script doit aller
|
||||
lire pour afficher les résultats.
|
||||
|
||||
Merci d'user de ce script avec parcimonie, et de ne pas jouer à
|
||||
"qui à la plus grosse".""", ['rouge']).encode(ENCODING)
|
49
utils/wol.py
49
utils/wol.py
|
@ -1,49 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import os, sys
|
||||
sys.path.append('/usr/scripts/gestion')
|
||||
from ldap_crans_test import crans_ldap
|
||||
|
||||
if len(sys.argv) > 1 : #Affichage de la syntaxe
|
||||
if (sys.argv[1] == '-h' or sys.argv[1] == '--help'):
|
||||
print 'Syntaxe:'
|
||||
print ' wol nom_de_la_machine'
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
login = os.getlogin()
|
||||
db = crans_ldap()
|
||||
try:
|
||||
aid = db.search('login=%s' % login)['adherent'][0]
|
||||
except IndexError:
|
||||
print 'Adherent introuvable !'
|
||||
sys.exit(0)
|
||||
|
||||
if len(sys.argv) > 1 : #on a un nom de machine a reveiller
|
||||
nom = sys.argv[1]
|
||||
print 'Recherche de la machine %s' % nom
|
||||
try:
|
||||
mid = db.search('host=%s' % nom)['machine'][0]
|
||||
except IndexError:
|
||||
print 'Machine non trouvee!' #l'user est un manche et tente de reveiller les morts
|
||||
sys.exit(0)
|
||||
else:
|
||||
print 'Machine trouvee!' #on a maintenant une machine a reveiller
|
||||
|
||||
if (mid not in aid.machines()) : #c'est sa machine ? Si oui, tout va bien, sinon...
|
||||
if 'Nounou' not in aid.droits() : #c'est une nounou? Si oui, tout va bien, sinon au revoir.
|
||||
print 'Vous n\'avez pas le droit de reveiller %s, ce n\'est pas votre machine' % nom
|
||||
sys.exit(0)
|
||||
|
||||
#On a une machine, et l'user a le droit de la reveiller, donc on lance le paquet magique
|
||||
etherwake = os.popen("/usr/bin/sudo /usr/sbin/etherwake -i crans %s" % mid.mac())
|
||||
print 'Paquet magique envoye a %s' % nom
|
||||
|
||||
else: #On n'a pas de nom de machine, on propose les machines de l'adherent
|
||||
print 'Quelle machine voulez vous reveiller ?'
|
||||
for machines in aid.machines() :
|
||||
print ' - %s' % machines.nom()
|
||||
print 'Syntaxe:'
|
||||
print ' wol nom_de_la_machine'
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue