2020-07-21 08:51:25 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
# This script is intended to be called automatically every day (e.g. via cron).
|
|
|
|
# It only output stuff if new ranks have to be inserted. Therefore the output
|
|
|
|
# may be redirected to email notifying about manual action to transfer the
|
|
|
|
# ranks to MySQL.
|
|
|
|
#
|
|
|
|
# Configure cron as the user running the DDNet-Server processes
|
|
|
|
#
|
|
|
|
# $ crontab -e
|
|
|
|
# 30 5 * * * /path/to/this/script/move_sqlite.py --from /path/to/ddnet-server.sqlite
|
|
|
|
#
|
|
|
|
# Afterwards configure a MTA (e.g. postfix) and the users email address.
|
|
|
|
|
|
|
|
import sqlite3
|
|
|
|
import argparse
|
|
|
|
from time import strftime
|
|
|
|
import os
|
|
|
|
|
2020-08-12 21:23:47 +00:00
|
|
|
def sqlite_table_exists(cursor, table):
|
|
|
|
cursor.execute("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='{}'".format(table))
|
|
|
|
return cursor.fetchone()[0] != 0
|
|
|
|
|
2020-07-21 08:51:25 +00:00
|
|
|
def sqlite_num_transfer(conn, table):
|
|
|
|
c = conn.cursor()
|
2020-08-12 21:23:47 +00:00
|
|
|
if not sqlite_table_exists(c, table):
|
|
|
|
return 0
|
2020-07-21 08:51:25 +00:00
|
|
|
c.execute('SELECT COUNT(*) FROM {}'.format(table))
|
|
|
|
num = c.fetchone()[0]
|
|
|
|
return num
|
|
|
|
|
|
|
|
def transfer(file_from, file_to):
|
|
|
|
conn_to = sqlite3.connect(file_to, isolation_level='EXCLUSIVE')
|
|
|
|
cursor_to = conn_to.cursor()
|
|
|
|
|
|
|
|
conn_from = sqlite3.connect(file_from, isolation_level='EXCLUSIVE')
|
|
|
|
for line in conn_from.iterdump():
|
|
|
|
cursor_to.execute(line)
|
|
|
|
print(line)
|
|
|
|
cursor_to.close()
|
|
|
|
conn_to.commit()
|
|
|
|
conn_to.close()
|
|
|
|
|
|
|
|
cursor_from = conn_from.cursor()
|
2020-08-12 21:23:47 +00:00
|
|
|
if sqlite_table_exists(cursor_from, 'record_race'):
|
|
|
|
cursor_from.execute('DELETE FROM record_race')
|
|
|
|
if sqlite_table_exists(cursor_from, 'record_teamrace'):
|
|
|
|
cursor_from.execute('DELETE FROM record_teamrace')
|
|
|
|
if sqlite_table_exists(cursor_from, 'record_saves'):
|
|
|
|
cursor_from.execute('DELETE FROM record_saves')
|
2020-07-21 08:51:25 +00:00
|
|
|
cursor_from.close()
|
|
|
|
conn_from.commit()
|
|
|
|
conn_from.close()
|
|
|
|
|
|
|
|
def main():
|
|
|
|
default_output = 'ddnet-server-' + strftime('%Y-%m-%d') + '.sqlite'
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
description='Move DDNet ranks, teamranks and saves from a possible active SQLite3 to a new one',
|
|
|
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
|
|
parser.add_argument('--from', '-f', dest='f',
|
|
|
|
default='ddnet-server.sqlite',
|
|
|
|
help='Input file where ranks are deleted from when moved successfully (default: ddnet-server.sqlite)')
|
|
|
|
parser.add_argument('--to', '-t',
|
|
|
|
default=default_output,
|
|
|
|
help='Output file where ranks are saved adds current date by default')
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
2020-08-12 21:23:47 +00:00
|
|
|
if not os.path.exists(args.f):
|
|
|
|
print("Warning: '{}' does not exist (yet). Is the path specified correctly?".format(args.f))
|
|
|
|
return
|
|
|
|
|
2020-07-21 08:51:25 +00:00
|
|
|
conn = sqlite3.connect(args.f)
|
|
|
|
num_ranks = sqlite_num_transfer(conn, 'record_race')
|
|
|
|
num_teamranks = sqlite_num_transfer(conn, 'record_teamrace')
|
|
|
|
num_saves = sqlite_num_transfer(conn, 'record_saves')
|
|
|
|
num = num_ranks + num_teamranks + num_saves
|
|
|
|
conn.close()
|
|
|
|
if num == 0:
|
|
|
|
return
|
|
|
|
|
|
|
|
print('{} new entries in backup database found ({} ranks, {} teamranks, {} saves'.format(num, num_ranks, num_teamranks, num_saves))
|
|
|
|
print('Moving entries from {} to {}'.format(
|
|
|
|
os.path.abspath(args.f),
|
|
|
|
os.path.abspath(args.to)))
|
|
|
|
sql_file = 'ddnet-server-' + strftime('%Y-%m-%d') + '.sql'
|
|
|
|
print("You can use the following commands to import the entries to MySQL (use sed 's/record_/prefix_/' for other database prefixes):")
|
|
|
|
print()
|
|
|
|
print((" echo '.dump --preserve-rowids' | sqlite3 {} | " + # including rowids, this forces sqlite to name all columns in each INSERT statement
|
|
|
|
"grep -E '^INSERT INTO record_(race|teamrace|saves)' | " + # filter out inserts
|
|
|
|
"sed -e 's/rowid,//' -e 's/VALUES([0-9]*,/VALUES(/' > {}") # filter out rowids again
|
|
|
|
.format(os.path.abspath(args.to), sql_file))
|
|
|
|
print(" mysql -u teeworlds -p'PW2' teeworlds < {}".format(sql_file))
|
|
|
|
print()
|
2020-08-12 21:25:44 +00:00
|
|
|
print("When the ranks are transfered successfully to mysql, {} can be removed".format(
|
|
|
|
os.path.abspath(args.to)))
|
2020-07-21 08:51:25 +00:00
|
|
|
print()
|
|
|
|
print("Log of the transfer:")
|
|
|
|
print()
|
|
|
|
|
|
|
|
transfer(args.f, args.to)
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|