add import/export functions

This commit is contained in:
mst 2024-11-26 15:16:42 +03:00
parent 283f2e5784
commit 86fb42c6f6

View file

@ -528,6 +528,156 @@ def generateFavicon(file_name):
resized_img_absolute_path = const.faviconDir / filename resized_img_absolute_path = const.faviconDir / filename
resized_img.save(resized_img_absolute_path) resized_img.save(resized_img_absolute_path)
def createExport():
try:
# just to test if connection works
conn = connectToDb()
conn.close()
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
timestamp_morereadable = datetime.now().strftime('%b %d, %Y %H:%M')
export_dir = const.exportsDir
temp_dir = const.tempDir
os.makedirs(export_dir, exist_ok=True)
os.makedirs(temp_dir, exist_ok=True)
config_dest_path = temp_dir / const.configFile
shutil.copy(const.configFile, config_dest_path)
# Export database to SQL file
dump_file = temp_dir / 'database.sql'
result = subprocess.Popen(
f'mysqldump --quote-names -u {dbUser} -p{dbPass} {dbName} --result-file={dump_file}',
stdin=subprocess.PIPE,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding="utf-8"
)
# absolutely dumb workaround for an error
time.sleep(1)
# Create export zip archive
zip_file_path = export_dir / f'export-{timestamp}.zip'
with zipfile.ZipFile(zip_file_path, 'w') as export_zip:
export_zip.write(config_dest_path, arcname=const.configFile)
export_zip.write(dump_file, arcname='database.sql')
# Add favicon and emojis folders to the zip archive
favicon_dir = Path('static/icons/favicon')
emojis_dir = Path('static/emojis')
if favicon_dir.exists():
for root, _, files in os.walk(favicon_dir):
for file in files:
file_path = Path(root) / file
export_zip.write(file_path, arcname=file_path.relative_to(favicon_dir.parent.parent))
if emojis_dir.exists():
for root, _, files in os.walk(emojis_dir):
for file in files:
file_path = Path(root) / file
export_zip.write(file_path, arcname=file_path.relative_to(emojis_dir.parent))
# Record export metadata
export_data = {
'timestamp_esc': timestamp,
'timestamp': timestamp_morereadable,
'downloadPath': str(zip_file_path)
}
appendToJSON(export_data, const.exportsFile)
shutil.rmtree(temp_dir)
return {'message': 'Export created successfully!'}
except mysql.connector.Error as e:
return {'error': str(e)}, 500
except Exception as e:
return {'error': str(e)}, 500
def importData(export_file):
try:
shutil.unpack_archive(export_file, const.tempDir)
# Replace config file
os.remove(const.configFile)
shutil.move(const.tempDir / const.configFile, Path.cwd() / const.configFile)
# Replace favicon and emojis folders
favicon_dest = Path('static/icons/favicon')
emojis_dest = Path('static/emojis')
shutil.rmtree(favicon_dest)
shutil.copytree(const.tempDir / 'icons' / 'favicon', favicon_dest)
shutil.rmtree(emojis_dest)
shutil.copytree(const.tempDir / 'emojis', emojis_dest)
# Restore database from SQL file
conn = connectToDb()
cursor = conn.cursor()
with open(const.tempDir / 'database.sql', 'r') as schema_file:
try:
# for some reason `cursor.execute(schema, multi=True)` doesn't work, so we use this instead
schema = schema_file.read()
queries = schema.split(';')
for query in queries:
cursor.execute(query)
except mysql.connector.Error as e:
return {'error': str(e)}, 500
finally:
cursor.close()
conn.close()
shutil.rmtree(const.tempDir)
return {'message': 'Data imported successfully!'}
except Exception as e:
return {'error': str(e)}, 500
# will probably get to it in 1.8.0 because my brain can't do it rn
"""
def retrospringImport(export_file):
shutil.unpack_archive(export_file, const.tempDir)
# probably a hack but whateva
export_dirname = Path(export_file).stem
export_dir = const.tempDir / export_dirname
conn = connectToDb()
cursor = conn.cursor()
questions_file = loadJSON(export_dir / 'questions.json')
answers_file = loadJSON(export_dir / 'answers.json')
# Extract answers list
questions_list = questions_file.get('questions', [])
answers_list = answers_file.get('answers', [])
# ['related']['question']['anonymous']
for question in questions_list:
# addQuestion(answer['related']['question']['anonymous'], question['content'], None, noAntispam=True)
for answer in answers_list:
print("anonymous:", answer['related']['question']['anonymous'])
print(question['id'], answer['content'], None)
# addAnswer(question['id'], answer['content'], None)
# shutil.rmtree(const.tempDir)
cursor.close()
conn.close()
"""
def deleteExport(timestamp):
try:
export_file = Path('static') / 'exports' / f'export-{timestamp}.zip'
data = loadJSON(const.exportsFile)
data = [export for export in data if export["timestamp_esc"] != timestamp]
export_file.unlink()
saveJSON(data, const.exportsFile)
return {'message': f'Export {timestamp} deleted successfully.'}
except Exception as e:
return {'error': str(e)}, 500
# reserved for 1.7.0 or later # reserved for 1.7.0 or later
""" """
def getUserIp(): def getUserIp():