-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move the quote database from JSON to SQL, for improved data security. With massive JSON files comes an increased chance of file corruption. The SQL database is located on the management portal.
- Loading branch information
1 parent
b9aa6e4
commit 0423bd1
Showing
9 changed files
with
401 additions
and
373 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,130 @@ | ||
import datetime | ||
import json | ||
import os | ||
|
||
from Framework.FileSystemAPI import DatabaseObjects | ||
from Framework.FileSystemAPI.ThreadedLogger import ThreadedLogger | ||
from Framework.GeneralUtilities import GeneralUtilities | ||
|
||
logger = None | ||
|
||
|
||
def initialize(management_portal_handler=None): | ||
global logger | ||
|
||
from Framework.FileSystemAPI.ThreadedLogger import ThreadedLogger | ||
logger = ThreadedLogger("DataMigrator", management_portal_handler) | ||
|
||
|
||
async def migrate_storage_metadata(guild: str, old_version: int) -> None: | ||
metadata_path = os.path.abspath( | ||
os.getcwd() + "/Storage/GuildStorageMetadata.json") | ||
|
||
with open(metadata_path, "r") as f: | ||
metadata = json.load(f) | ||
|
||
# Migrate from version 1 to version 2 | ||
if old_version == 1: | ||
logger.log_info("Migrating guild storage metadata for guild " + guild + " from version 1 to version 2") | ||
old_version = 2 | ||
# Version 2 renamed the custom commands metadata file | ||
metadata["guilds"][guild] = 2 | ||
object_path = os.path.abspath(os.getcwd() + "/Storage/{}/CustomCommands/metadata.json".format(str(guild))) | ||
os.renames(object_path, object_path.replace("metadata.json", "CommandsMetadata.json")) | ||
|
||
with open(metadata_path, "w") as f: | ||
json.dump(metadata, f, indent=4) | ||
|
||
# Migrate from version 2 to version 3 | ||
if old_version == 2: | ||
logger.log_info("Migrating guild storage metadata for guild " + guild + " from version 2 to version 3") | ||
old_version = 3 | ||
# Version 3 changed the author key in the quotes file to use ints instead of strings | ||
metadata["guilds"][guild] = 3 | ||
|
||
with open(await DatabaseObjects.get_quotes_database(int(guild)), "r") as f: | ||
quotes = json.load(f) | ||
|
||
for quote in quotes: | ||
try: | ||
quote["author"] = int(await GeneralUtilities.strip_usernames(str(quote["author"]))) | ||
except ValueError: | ||
pass | ||
|
||
with open(await DatabaseObjects.get_quotes_database(int(guild)), "w") as f: | ||
json.dump(quotes, f, indent=4) | ||
|
||
with open(metadata_path, "w") as f: | ||
json.dump(metadata, f) | ||
|
||
# Migrate from version 3 to version 4 | ||
if old_version == 3: | ||
logger.log_info("Migrating guild storage metadata for guild " + guild + " from version 3 to version 4") | ||
old_version = 4 | ||
# Version 4 added a date field and a "quoted_by" field. Old entries will have the missing fields | ||
# set with a value of "Unknown" | ||
metadata["guilds"][guild] = 4 | ||
|
||
with open(await DatabaseObjects.get_quotes_database(int(guild)), "r") as f: | ||
quotes = json.load(f) | ||
|
||
for quote in quotes: | ||
try: | ||
quote["date"] = "Unknown" | ||
quote["quoted_by"] = "Unknown" | ||
except ValueError: | ||
pass | ||
|
||
with open(await DatabaseObjects.get_quotes_database(int(guild)), "w") as f: | ||
json.dump(quotes, f, indent=4) | ||
|
||
with open(metadata_path, "w") as f: | ||
json.dump(metadata, f) | ||
|
||
# Migrate from version 4 to version 5 | ||
if old_version == 4: | ||
logger.log_info("Migrating guild storage metadata for guild " + guild + " from version 4 to version 5") | ||
old_version = 5 | ||
# Version 5 removed the Modules.json file | ||
metadata["guilds"][guild] = 5 | ||
|
||
object_path = os.path.abspath(os.getcwd() + "/Storage/{}/Settings/Modules.json".format(str(guild))) | ||
os.remove(object_path) | ||
|
||
with open(metadata_path, "w") as f: | ||
json.dump(metadata, f) | ||
from Framework.ManagementPortal.ManagementPortalHandler import ManagementPortalHandler | ||
|
||
|
||
class DataMigrator: | ||
|
||
def __init__(self, management_portal_handler: ManagementPortalHandler): | ||
self.logger = ThreadedLogger("DataMigrator", management_portal_handler) | ||
self.mp = management_portal_handler | ||
|
||
async def migrate_storage_metadata(self, guild: str, old_version: int) -> None: | ||
metadata_path = os.path.abspath( | ||
os.getcwd() + "/Storage/GuildStorageMetadata.json") | ||
|
||
with open(metadata_path, "r") as metadata_file: | ||
metadata = json.load(metadata_file) | ||
|
||
# Migrate from version 1 to version 2 | ||
if old_version == 1: | ||
self.logger.log_info("Migrating guild storage metadata for guild " + guild + " from version 1 to version 2") | ||
old_version = 2 | ||
# Version 2 renamed the custom commands metadata file | ||
metadata["guilds"][guild] = 2 | ||
object_path = os.path.abspath(os.getcwd() + "/Storage/{}/CustomCommands/metadata.json".format(str(guild))) | ||
os.renames(object_path, object_path.replace("metadata.json", "CommandsMetadata.json")) | ||
|
||
# Migrate from version 2 to version 3 | ||
if old_version == 2: | ||
self.logger.log_info("Migrating guild storage metadata for guild " + guild + " from version 2 to version 3") | ||
old_version = 3 | ||
# Version 3 changed the author key in the quotes file to use ints instead of strings | ||
metadata["guilds"][guild] = 3 | ||
|
||
with open(await DatabaseObjects.get_quotes_database(int(guild)), "r") as quotes_file: | ||
quotes = json.load(quotes_file) | ||
|
||
for quote in quotes: | ||
try: | ||
quote["author"] = int(await GeneralUtilities.strip_usernames(str(quote["author"]))) | ||
except ValueError: | ||
pass | ||
|
||
with open(await DatabaseObjects.get_quotes_database(int(guild)), "w") as quotes_file: | ||
json.dump(quotes, quotes_file, indent=4) | ||
|
||
# Migrate from version 3 to version 4 | ||
if old_version == 3: | ||
self.logger.log_info("Migrating guild storage metadata for guild " + guild + " from version 3 to version 4") | ||
old_version = 4 | ||
# Version 4 added a date field and a "quoted_by" field. Old entries will have the missing fields | ||
# set with a value of "Unknown" | ||
metadata["guilds"][guild] = 4 | ||
|
||
with open(await DatabaseObjects.get_quotes_database(int(guild)), "r") as quotes_file: | ||
quotes = json.load(quotes_file) | ||
|
||
for quote in quotes: | ||
try: | ||
quote["date"] = "Unknown" | ||
quote["quoted_by"] = "Unknown" | ||
except ValueError: | ||
pass | ||
|
||
with open(await DatabaseObjects.get_quotes_database(int(guild)), "w") as quotes_file: | ||
json.dump(quotes, quotes_file, indent=4) | ||
|
||
# Migrate from version 4 to version 5 | ||
if old_version == 4: | ||
self.logger.log_info("Migrating guild storage metadata for guild " + guild + " from version 4 to version 5") | ||
old_version = 5 | ||
# Version 5 removed the Modules.json file | ||
metadata["guilds"][guild] = 5 | ||
|
||
object_path = os.path.abspath(os.getcwd() + "/Storage/{}/Settings/Modules.json".format(str(guild))) | ||
os.remove(object_path) | ||
|
||
# Migrate from version 5 to version 6 | ||
if old_version == 5: | ||
self.logger.log_info("Migrating guild storage metadata for guild " + guild + " from version 5 to version 6") | ||
old_version = 6 | ||
# Version 6 migrates all JSON storages to a MySQL database hosted on its management portal | ||
metadata["guilds"][guild] = 6 | ||
|
||
# Migrate the quotes database | ||
with open(await DatabaseObjects.get_quotes_database(int(guild)), "r") as quotes_file: | ||
json_data = json.load(quotes_file) | ||
|
||
# Replace all "Unknown" date values with an empty timestamp | ||
for quote in json_data: | ||
if quote["date"] == "Unknown": | ||
quote["date"] = datetime.datetime(1970, 1, 1, 0, 0, 0).isoformat() | ||
|
||
# Replace all "Unknown" quoted_by values with an empty ID | ||
for quote in json_data: | ||
if quote["quoted_by"] == "Unknown": | ||
quote["quoted_by"] = 0 | ||
|
||
# Check the author IDs and ensure it is a valid integer | ||
delete_list = [] | ||
for quote in json_data: | ||
try: | ||
quote["author"] = int(quote["author"]) | ||
except ValueError: | ||
# The quote will be deleted | ||
# Store deleted quotes in a separate file as a backup | ||
delete_list.append(quote) | ||
json_data.remove(quote) | ||
|
||
if len(delete_list) > 0: | ||
# Dump the deleted quotes to a file | ||
backup_file_name = "DeletedQuotesBackup_{}.json".format(guild) | ||
with open(await DatabaseObjects.get_backup_directory() + "\\" + backup_file_name, "w") as backup_file: | ||
json.dump(delete_list, backup_file, indent=4) | ||
|
||
self.logger.log_warning("Deleted {} quotes from guild {} due to invalid author IDs".format(len(delete_list), guild)) | ||
|
||
data = json.dumps(json_data) | ||
await self.mp.data_migration.migrate_quotes(int(guild), data) | ||
|
||
# Delete the old quotes database | ||
os.remove(await DatabaseObjects.get_quotes_database(int(guild))) | ||
|
||
with open(metadata_path, "w") as metadata_file: | ||
json.dump(metadata, metadata_file, indent=4) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from enum import Enum | ||
|
||
|
||
class APIEndpoints(str, Enum): | ||
READY = "/v2/bot_ready.php" | ||
UPDATE_LATENCY = "/v2/bot_update_latency.php" | ||
UPDATE_COMMAND_USED = "/v2/bot_update_command_used.php" | ||
LOG_DATA = "/v2/bot_log_data.php" | ||
CHECK_PENDING_COMMANDS = "/v2/bot_check_pending_commands.php" | ||
UPDATE_COMMAND_COMPLETED = "/v2/bot_update_command_completed.php" | ||
GET_CONFIGURATION = "/v2/configurations/portal_get_configuration.php" | ||
MIGRATE_QUOTES = "/v2/migrations/migrate_quotes.php" | ||
GET_QUOTE = "/v2/modules/quotes/get_quote.php" | ||
ADD_QUOTE = "/v2/modules/quotes/add_quote.php" | ||
REMOVE_QUOTE = "/v2/modules/quotes/remove_quote.php" | ||
GET_QUOTE_COUNT = "/v2/modules/quotes/get_quote_count.php" | ||
EDIT_QUOTE = "/v2/modules/quotes/edit_quote.php" | ||
SEARCH_QUOTES = "/v2/modules/quotes/search_quotes.php" | ||
LIST_RECENT_QUOTES = "/v2/modules/quotes/list_recent_quotes.php" |
Oops, something went wrong.