book_generator/app.py

359 lines
No EOL
11 KiB
Python

from flask import Flask, render_template, request, jsonify
import os
import json
from datetime import datetime, timedelta
import re
app = Flask(__name__, static_folder='static')
def load_org_file(filename):
if os.path.exists(filename):
with open(filename, 'r', encoding='utf-8') as f:
return f.read()
return ""
def save_org_file(filename, content):
with open(filename, 'w', encoding='utf-8') as f:
f.write(content)
def extract_characters(content):
characters = []
current_character = None
current_content = []
for line in content.split('\n'):
if line.startswith('** '):
if current_character:
characters.append({
'name': current_character,
'content': '\n'.join(current_content)
})
current_character = line[3:].strip()
current_content = []
elif current_character:
current_content.append(line)
if current_character:
characters.append({
'name': current_character,
'content': '\n'.join(current_content)
})
return characters
def extract_plots(content):
plots = []
current_plot = None
current_content = []
current_level = 0
for line in content.split('\n'):
if line.startswith('*'):
if current_plot:
current_plot['content'] = '\n'.join(current_content)
plots.append(current_plot)
level = len(line) - len(line.lstrip('*'))
current_plot = {
'name': line.lstrip('*').strip(),
'level': level,
'content': '',
'subplots': []
}
current_content = []
elif current_plot:
current_content.append(line)
if current_plot:
current_plot['content'] = '\n'.join(current_content)
plots.append(current_plot)
# Organiser les intrigues en hiérarchie
hierarchical_plots = []
plot_stack = []
for plot in plots:
while plot_stack and plot['level'] <= plot_stack[-1]['level']:
plot_stack.pop()
if plot_stack:
plot_stack[-1]['subplots'].append(plot)
else:
hierarchical_plots.append(plot)
plot_stack.append(plot)
return hierarchical_plots
def update_data_json():
data = load_data()
# Charger et traiter les personnages
characters_content = load_org_file('personnages.org')
characters = extract_characters(characters_content)
data['characters'] = characters
# Charger et traiter les intrigues
plots_content = load_org_file('intrigues.org')
plots = extract_plots(plots_content)
data['plots'] = plots
save_data(data)
return data
def count_words(text):
# Ignorer les lignes de propriétés et d'export
lines = text.split('\n')
filtered_lines = [line for line in lines if not any(line.startswith(prefix) for prefix in
[':PROPERTIES:', ':ID:', ':END:', '#+BEGIN_EXPORT', '#+END_EXPORT', '#+'])]
# Compter les mots dans les lignes filtrées
words = ' '.join(filtered_lines).split()
return len(words)
def load_data():
if os.path.exists('data.json'):
with open('data.json', 'r', encoding='utf-8') as f:
return json.load(f)
return {}
def save_data(data):
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
def get_words_today():
data = load_data()
today = datetime.now().strftime('%Y-%m-%d')
yesterday = (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
# Si on n'a pas de données pour aujourd'hui, on crée une entrée
if today not in data:
data[today] = {
'words': 0,
'last_update': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
save_data(data)
# Trouver le jour précédent le plus proche qui a des données
previous_day = None
previous_words = 0
current_date = datetime.now() - timedelta(days=1)
while current_date >= datetime.strptime('2000-01-01', '%Y-%m-%d'):
date_str = current_date.strftime('%Y-%m-%d')
if date_str in data:
previous_day = date_str
previous_words = data[date_str]['words']
break
current_date -= timedelta(days=1)
# Si on n'a pas trouvé de jour précédent, on utilise le nombre de mots actuel comme référence
if not previous_day:
with open('livre.org', 'r', encoding='utf-8') as f:
content = f.read()
previous_words = count_words(content)
data[yesterday] = {
'words': previous_words,
'last_update': (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S')
}
save_data(data)
# Calculer la progression en différence avec le jour précédent
words_today = data[today]['words']
progress = max(0, words_today - previous_words)
return progress
@app.route('/')
def index():
with open('livre.org', 'r', encoding='utf-8') as f:
content = f.read()
words_today = get_words_today()
data = update_data_json()
return render_template('index.html', content=content, words_today=words_today,
characters=data.get('characters', []), plots=data.get('plots', []))
@app.route('/update', methods=['POST'])
def update():
content = request.form.get('content', '')
editor_title = request.form.get('editor_title', '')
# Déterminer le fichier de destination en fonction du titre de l'éditeur
if 'Personnage:' in editor_title:
current_file = 'personnages.org'
elif 'Intrigue:' in editor_title:
current_file = 'intrigues.org'
elif editor_title == 'Intrigues':
current_file = 'intrigues.org'
else:
current_file = 'livre.org'
with open(current_file, 'w', encoding='utf-8') as f:
f.write(content)
# Mettre à jour le nombre de mots pour aujourd'hui si c'est le fichier principal
if current_file == 'livre.org':
data = load_data()
today = datetime.now().strftime('%Y-%m-%d')
data[today] = {
'words': count_words(content),
'last_update': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
save_data(data)
return jsonify({'words_today': get_words_today()})
@app.route('/words_today')
def words_today():
return jsonify({'words': get_words_today()})
@app.route('/progress_data')
def progress_data():
data = load_data()
# Trier les dates
dates = sorted(data.keys(), reverse=True)
# Prendre les 7 derniers jours
dates = dates[:7]
# Préparer les données pour le graphique
chart_data = {
'labels': [],
'words': [],
'progress': []
}
for date in dates:
chart_data['labels'].append(date)
if date in data and 'words' in data[date]:
chart_data['words'].append(data[date]['words'])
else:
chart_data['words'].append(0)
# Calculer la progression entre chaque jour
for i in range(len(chart_data['words'])):
if i < len(chart_data['words']) - 1:
progress = max(0, chart_data['words'][i] - chart_data['words'][i + 1])
else:
progress = 0
chart_data['progress'].append(progress)
return jsonify(chart_data)
@app.route('/update_character', methods=['POST'])
def update_character():
name = request.form.get('name')
content = request.form.get('content')
characters_content = load_org_file('personnages.org')
characters = extract_characters(characters_content)
# Mettre à jour ou ajouter le personnage
found = False
for char in characters:
if char['name'] == name:
char['content'] = content
found = True
break
if not found:
characters.append({
'name': name,
'content': content
})
# Sauvegarder le fichier
new_content = []
for char in characters:
new_content.append(f"* {char['name']}")
new_content.append(char['content'])
save_org_file('personnages.org', '\n'.join(new_content))
update_data_json()
return jsonify({'status': 'success'})
@app.route('/update_plot', methods=['POST'])
def update_plot():
name = request.form.get('name')
content = request.form.get('content')
plots_content = load_org_file('intrigues.org')
plots = extract_plots(plots_content)
# Mettre à jour ou ajouter l'intrigue
found = False
for plot in plots:
if plot['name'] == name:
plot['content'] = content
found = True
break
if not found:
plots.append({
'name': name,
'content': content
})
# Sauvegarder le fichier
new_content = []
for plot in plots:
new_content.append(f"* {plot['name']}")
new_content.append(plot['content'])
save_org_file('intrigues.org', '\n'.join(new_content))
update_data_json()
return jsonify({'status': 'success'})
@app.route('/get_character', methods=['POST'])
def get_character():
name = request.form.get('name')
characters_content = load_org_file('personnages.org')
characters = extract_characters(characters_content)
for char in characters:
if char['name'] == name:
return jsonify({
'content': f"* {char['name']}\n{char['content']}"
})
return jsonify({'error': 'Personnage non trouvé'}), 404
@app.route('/get_plot', methods=['POST'])
def get_plot():
name = request.form.get('name')
plots_content = load_org_file('intrigues.org')
plots = extract_plots(plots_content)
for plot in plots:
if plot['name'] == name:
return jsonify({
'content': f"* {plot['name']}\n{plot['content']}"
})
return jsonify({'error': 'Intrigue non trouvée'}), 404
@app.route('/get_book')
def get_book():
content = load_org_file('livre.org')
return jsonify({'content': content})
@app.route('/get_plots_file')
def get_plots_file():
try:
with open('intrigues.org', 'r', encoding='utf-8') as f:
content = f.read()
return jsonify({'content': content})
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/get_characters_file')
def get_characters_file():
try:
with open('personnages.org', 'r', encoding='utf-8') as f:
content = f.read()
return jsonify({'content': content})
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(debug=True)