updated
This commit is contained in:
102
app.py
102
app.py
@@ -13,6 +13,7 @@ from pptx.util import Inches
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
import io
|
import io
|
||||||
import threading
|
import threading
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
|
||||||
app = Flask(__name__, instance_relative_config=True)
|
app = Flask(__name__, instance_relative_config=True)
|
||||||
|
|
||||||
@@ -87,36 +88,7 @@ def add_image_to_playlist(file, filename, duration, target_type, target_id):
|
|||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
def convert_ppt_to_images(input_file, output_folder):
|
|
||||||
"""
|
|
||||||
Converts a PowerPoint file (.ppt or .pptx) to images using LibreOffice.
|
|
||||||
Each slide is saved as a separate image in the output folder.
|
|
||||||
"""
|
|
||||||
if not os.path.exists(output_folder):
|
|
||||||
os.makedirs(output_folder)
|
|
||||||
|
|
||||||
# Convert the PowerPoint file to images using LibreOffice
|
|
||||||
command = [
|
|
||||||
'libreoffice',
|
|
||||||
'--headless',
|
|
||||||
'--convert-to', 'png',
|
|
||||||
'--outdir', output_folder,
|
|
||||||
input_file
|
|
||||||
]
|
|
||||||
try:
|
|
||||||
subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
print(f"PPT file converted to images: {input_file}")
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
print(f"Error converting PPT to images: {e.stderr.decode()}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Rename the generated images to follow the naming convention
|
|
||||||
base_name = os.path.splitext(os.path.basename(input_file))[0]
|
|
||||||
for i, file_name in enumerate(sorted(os.listdir(output_folder))):
|
|
||||||
if file_name.endswith('.png'):
|
|
||||||
new_name = f"{base_name}_{i + 1}.png"
|
|
||||||
os.rename(os.path.join(output_folder, file_name), os.path.join(output_folder, new_name))
|
|
||||||
return True
|
|
||||||
|
|
||||||
def convert_pdf_to_images(input_file, output_folder):
|
def convert_pdf_to_images(input_file, output_folder):
|
||||||
"""
|
"""
|
||||||
@@ -210,6 +182,45 @@ def convert_video_and_update_playlist(file_path, original_filename, target_type,
|
|||||||
else:
|
else:
|
||||||
print(f"Video conversion failed for: {file_path}")
|
print(f"Video conversion failed for: {file_path}")
|
||||||
|
|
||||||
|
def convert_pptx_to_images(input_file, output_folder):
|
||||||
|
"""
|
||||||
|
Converts a PowerPoint file (.pptx) to images using python-pptx.
|
||||||
|
Each slide is saved as a separate image in the output folder.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if not os.path.exists(output_folder):
|
||||||
|
os.makedirs(output_folder)
|
||||||
|
|
||||||
|
# Load the PowerPoint presentation
|
||||||
|
presentation = Presentation(input_file)
|
||||||
|
base_name = os.path.splitext(os.path.basename(input_file))[0]
|
||||||
|
|
||||||
|
for i, slide in enumerate(presentation.slides):
|
||||||
|
# Create a blank image for the slide
|
||||||
|
img = Image.new('RGB', (1920, 1080), color='white') # Adjust resolution as needed
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
|
# Extract slide content (text, shapes, etc.)
|
||||||
|
for shape in slide.shapes:
|
||||||
|
if shape.has_text_frame:
|
||||||
|
text = shape.text_frame.text
|
||||||
|
draw.text((50, 50 + i * 20), text, fill='black') # Adjust position and styling
|
||||||
|
|
||||||
|
# Save the image
|
||||||
|
image_filename = f"{base_name}_slide_{i + 1}.jpg"
|
||||||
|
image_path = os.path.join(output_folder, image_filename)
|
||||||
|
img.save(image_path, 'JPEG')
|
||||||
|
print(f"Slide {i + 1} saved as image: {image_path}")
|
||||||
|
|
||||||
|
# Delete the original PPTX file after conversion
|
||||||
|
if os.path.exists(input_file):
|
||||||
|
os.remove(input_file)
|
||||||
|
print(f"Original PPTX file deleted: {input_file}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing PPTX file: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
# Convert EMU to pixels
|
# Convert EMU to pixels
|
||||||
def emu_to_pixels(emu):
|
def emu_to_pixels(emu):
|
||||||
@@ -321,13 +332,13 @@ def upload_content():
|
|||||||
# Handle PPT files
|
# Handle PPT files
|
||||||
elif media_type == 'ppt':
|
elif media_type == 'ppt':
|
||||||
print(f"Processing PPT file: {file_path}")
|
print(f"Processing PPT file: {file_path}")
|
||||||
success = convert_ppt_to_images(file_path, app.config['UPLOAD_FOLDER'])
|
success = convert_pptx_to_images(file_path, app.config['UPLOAD_FOLDER'])
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
# Add each slide image to the playlist
|
# Add each slide image to the playlist
|
||||||
base_name = os.path.splitext(filename)[0]
|
base_name = os.path.splitext(filename)[0]
|
||||||
for slide_image in sorted(os.listdir(app.config['UPLOAD_FOLDER'])):
|
for slide_image in sorted(os.listdir(app.config['UPLOAD_FOLDER'])):
|
||||||
if slide_image.startswith(base_name) and slide_image.endswith('.png'):
|
if slide_image.startswith(base_name) and slide_image.endswith('.jpg'):
|
||||||
if target_type == 'group':
|
if target_type == 'group':
|
||||||
group = Group.query.get_or_404(target_id)
|
group = Group.query.get_or_404(target_id)
|
||||||
for player in group.players:
|
for player in group.players:
|
||||||
@@ -337,22 +348,12 @@ def upload_content():
|
|||||||
new_content = Content(file_name=slide_image, duration=duration, player_id=target_id)
|
new_content = Content(file_name=slide_image, duration=duration, player_id=target_id)
|
||||||
db.session.add(new_content)
|
db.session.add(new_content)
|
||||||
|
|
||||||
# Commit the changes to the database
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
# Remove the original PPT file after processing
|
|
||||||
if os.path.exists(file_path):
|
|
||||||
os.remove(file_path)
|
|
||||||
print(f"Original PPT file deleted: {file_path}")
|
|
||||||
else:
|
|
||||||
print(f"Failed to process PPT file: {file_path}")
|
|
||||||
flash(f"Failed to process PPT file: {file_path}", 'danger')
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error processing file {filename}: {e}")
|
print(f"Error processing file {file.filename}: {e}")
|
||||||
flash(f"Error processing file {filename}: {e}", 'danger')
|
flash(f"Error processing file {file.filename}: {e}", 'danger')
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
return redirect(return_url)
|
return redirect(return_url)
|
||||||
|
|
||||||
# Handle GET request
|
# Handle GET request
|
||||||
@@ -366,6 +367,10 @@ def upload_content():
|
|||||||
return render_template('upload_content.html', target_type=target_type, target_id=target_id, players=players, groups=groups, return_url=return_url)
|
return render_template('upload_content.html', target_type=target_type, target_id=target_id, players=players, groups=groups, return_url=return_url)
|
||||||
|
|
||||||
|
|
||||||
|
# Define global variables for server version and build date
|
||||||
|
SERVER_VERSION = "1.0.0"
|
||||||
|
BUILD_DATE = "2025-06-25"
|
||||||
|
|
||||||
@app.route('/admin')
|
@app.route('/admin')
|
||||||
@login_required
|
@login_required
|
||||||
@admin_required
|
@admin_required
|
||||||
@@ -373,7 +378,14 @@ def admin():
|
|||||||
logo_exists = os.path.exists(os.path.join(app.config['UPLOAD_FOLDERLOGO'], 'logo.png'))
|
logo_exists = os.path.exists(os.path.join(app.config['UPLOAD_FOLDERLOGO'], 'logo.png'))
|
||||||
login_picture_exists = os.path.exists(os.path.join(app.config['UPLOAD_FOLDERLOGO'], 'login_picture.png'))
|
login_picture_exists = os.path.exists(os.path.join(app.config['UPLOAD_FOLDERLOGO'], 'login_picture.png'))
|
||||||
users = User.query.all()
|
users = User.query.all()
|
||||||
return render_template('admin.html', users=users, logo_exists=logo_exists, login_picture_exists=login_picture_exists)
|
return render_template(
|
||||||
|
'admin.html',
|
||||||
|
users=users,
|
||||||
|
logo_exists=logo_exists,
|
||||||
|
login_picture_exists=login_picture_exists,
|
||||||
|
server_version=SERVER_VERSION,
|
||||||
|
build_date=BUILD_DATE
|
||||||
|
)
|
||||||
|
|
||||||
@app.route('/admin/change_role/<int:user_id>', methods=['POST'])
|
@app.route('/admin/change_role/<int:user_id>', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
|||||||
Binary file not shown.
30
ppt
Normal file
30
ppt
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
def convert_ppt_to_images(input_file, output_folder):
|
||||||
|
"""
|
||||||
|
Converts a PowerPoint file (.ppt or .pptx) to images using LibreOffice.
|
||||||
|
Each slide is saved as a separate image in the output folder.
|
||||||
|
"""
|
||||||
|
if not os.path.exists(output_folder):
|
||||||
|
os.makedirs(output_folder)
|
||||||
|
|
||||||
|
# Convert the PowerPoint file to images using LibreOffice
|
||||||
|
command = [
|
||||||
|
'libreoffice',
|
||||||
|
'--headless',
|
||||||
|
'--convert-to', 'png',
|
||||||
|
'--outdir', output_folder,
|
||||||
|
input_file
|
||||||
|
]
|
||||||
|
try:
|
||||||
|
subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
print(f"PPT file converted to images: {input_file}")
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error converting PPT to images: {e.stderr.decode()}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Rename the generated images to follow the naming convention
|
||||||
|
base_name = os.path.splitext(os.path.basename(input_file))[0]
|
||||||
|
for i, file_name in enumerate(sorted(os.listdir(output_folder))):
|
||||||
|
if file_name.endswith('.png'):
|
||||||
|
new_name = f"{base_name}_{i + 1}.png"
|
||||||
|
os.rename(os.path.join(output_folder, file_name), os.path.join(output_folder, new_name))
|
||||||
|
return True
|
||||||
BIN
static/uploads/informare_tombola_slide_1.jpg
Normal file
BIN
static/uploads/informare_tombola_slide_1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
@@ -195,6 +195,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 col-12">
|
||||||
|
<!-- Server Info Card -->
|
||||||
|
<div class="card mb-4 {{ 'dark-mode' if theme == 'dark' else '' }}">
|
||||||
|
<div class="card-header">
|
||||||
|
<h2>Server Info</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p><strong>Server Version:</strong> {{ server_version }}</p>
|
||||||
|
<p><strong>Date of Build:</strong> {{ build_date }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary">Back to Dashboard</a>
|
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary">Back to Dashboard</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user