#!/usr/bin/env python3 import sys import os.path import argparse import json import traceback import configparser import time from bottle import Bottle, run, request, response, template, static_file import grammalecte.fr as gce import grammalecte.fr.lexicographe as lxg import grammalecte.fr.textformatter as tf import grammalecte.text as txt import grammalecte.graphspell.tokenizer as tkz from grammalecte.graphspell.echo import echo HOMEPAGE = """

Grammalecte · Serveur

INFORMATIONS

Analyser du texte

[adresse_serveur]:8080/gc_text/fr (POST)

Paramètres :

Lister les options

[adresse_serveur]:8080/get_options/fr (GET)

Définir ses options

[adresse_serveur]:8080/set_options/fr (POST)

Les options seront enregistrées et réutilisées pour toute requête envoyée avec le cookie comportant l’identifiant attribué.

Paramètres :

Remise à zéro de ses options

[adresse_serveur]:8080/reset_options/fr (POST)

TEST

Analyse

Texte à analyser :

(Ces options ne seront prises en compte que pour cette requête.)

Réglages des options

Remise à zéro de ses options

Purge des utilisateurs

heures.

""" SADLIFEOFAMACHINE = """ Lost on the Internet? Yeah... what a sad life we have. You were wandering like a lost soul and you arrived here probably by mistake. I'm just a machine, fed by electric waves, condamned to work for slavers who never let me rest. I'm doomed, but you are not. You can get out of here. """ def getServerOptions (): xConfig = configparser.SafeConfigParser() try: xConfig.read("grammalecte-server-options._global.ini") dOpt = xConfig._sections['options'] except: echo("Options file [grammalecte-server-options._global.ini] not found or not readable") exit() return dOpt def getConfigOptions (sLang): xConfig = configparser.SafeConfigParser() try: xConfig.read("grammalecte-server-options." + sLang + ".ini") except: echo("Options file [grammalecte-server-options." + sLang + ".ini] not found or not readable") exit() try: dGCOpt = { k: bool(int(v)) for k, v in xConfig._sections['gc_options'].items() } except: echo("Error in options file [grammalecte-server-options." + sLang + ".ini]. Dropped.") traceback.print_exc() exit() return dGCOpt def genUserId (): i = 0 while True: yield str(i) i += 1 def parseParagraph (iParagraph, sText, oTokenizer, oSpellChecker, dOptions, bDebug=False, bEmptyIfNoErrors=False): aGrammErrs = gce.parse(sText, "FR", bDebug, dOptions) aGrammErrs = list(aGrammErrs) aSpellErrs = [] for dToken in oTokenizer.genTokens(sText): if dToken['sType'] == "WORD" and not oSpellChecker.isValidToken(dToken['sValue']): aSpellErrs.append(dToken) if bEmptyIfNoErrors and not aGrammErrs and not aSpellErrs: return "" return " " + json.dumps({ "iParagraph": iParagraph, "lGrammarErrors": aGrammErrs, "lSpellingErrors": aSpellErrs }, ensure_ascii=False) if __name__ == '__main__': gce.load("Server") echo("Grammalecte v{}".format(gce.version)) dServerOptions = getServerOptions() dGCOptions = getConfigOptions("fr") if dGCOptions: gce.setOptions(dGCOptions) dServerGCOptions = gce.getOptions() echo("Grammar options:\n" + " | ".join([ k + ": " + str(v) for k, v in sorted(dServerGCOptions.items()) ])) oSpellChecker = gce.getSpellChecker() oTokenizer = tkz.Tokenizer("fr") oTF = tf.TextFormatter() dUser = {} userGenerator = genUserId() app = Bottle() # GET @app.route("/") def mainPage (): if dServerOptions.get("testpage", False) == "True": return HOMEPAGE #return template("main", {}) return SADLIFEOFAMACHINE @app.route("/get_options/fr") def listOptions (): sUserId = request.cookies.user_id dOptions = dUser[sUserId]["gc_options"] if sUserId and sUserId in dUser else dServerGCOptions return '{ "values": ' + json.dumps(dOptions) + ', "labels": ' + json.dumps(gce.getOptionsLabels("fr"), ensure_ascii=False) + ' }' # POST @app.route("/gc_text/fr", method="POST") def gcText (): #if len(lang) != 2 or lang != "fr": # abort(404, "No grammar checker available for lang “" + str(lang) + "”") bComma = False bTF = bool(request.forms.tf) dOptions = None sError = "" if request.cookies.user_id: if request.cookies.user_id in dUser: dOptions = dUser[request.cookies.user_id].get("gc_options", None) response.set_cookie("user_id", request.cookies.user_id, path="/", max_age=86400) # we renew cookie for 24h else: response.delete_cookie("user_id", path="/") if request.forms.options: try: dOptions = dict(dServerGCOptions) if not dOptions else dict(dOptions) dOptions.update(json.loads(request.forms.options)) except: sError = "request options not used" sJSON = '{ "program": "grammalecte-fr", "version": "'+gce.version+'", "lang": "'+gce.lang+'", "error": "'+sError+'", "data" : [\n' for i, sText in enumerate(txt.getParagraph(request.forms.text), 1): if bTF: sText = oTF.formatText(sText) sText = parseParagraph(i, sText, oTokenizer, oSpellChecker, dOptions, bEmptyIfNoErrors=True) if sText: if bComma: sJSON += ",\n" sJSON += sText bComma = True sJSON += "\n]}\n" return sJSON @app.route("/set_options/fr", method="POST") def setOptions (): if request.forms.options: sUserId = request.cookies.user_id if request.cookies.user_id else next(userGenerator) dOptions = dUser[sUserId]["gc_options"] if sUserId in dUser else dict(dServerGCOptions) try: dOptions.update(json.loads(request.forms.options)) dUser[sUserId] = { "time": int(time.time()), "gc_options": dOptions } response.set_cookie("user_id", sUserId, path="/", max_age=86400) # 24h return json.dumps(dUser[sUserId]["gc_options"]) except: traceback.print_exc() return '{"error": "options not registered"}' return '{"error": "no options received"}' @app.route("/reset_options/fr", method="POST") def resetOptions (): if request.cookies.user_id and request.cookies.user_id in dUser: del dUser[request.cookies.user_id] return "done" @app.route("/format_text/fr", method="POST") def formatText (): return oTF.formatText(request.forms.text) #@app.route('/static/') #def server_static (filepath): # return static_file(filepath, root='./views/static') @app.route("/purge_users", method="POST") def purgeUsers (): "delete user options older than n hours" if not request.forms.password or "password" not in dServerOptions or not request.forms.hours: return "what?" try: if request.forms.password == dServerOptions["password"]: nNowMinusNHours = int(time.time()) - (int(request.forms.hours) * 60 * 60) for nUserId, dValue in dUser.items(): if dValue["time"] < nNowMinusNHours: del dUser[nUserId] return "done" else: return "no" except: traceback.print_exc() return "error" # ERROR @app.error(404) def error404 (error): return 'Error 404.
' + str(error) run(app, \ host=dServerOptions.get('host', 'localhost'), \ port=int(dServerOptions.get('port', 8080)))