Skip to content

Commit

Permalink
Merge pull request #37 from ramazanoacar/add/deletion-of-all-data
Browse files Browse the repository at this point in the history
Add/deletion of all data
  • Loading branch information
berkingurcan authored Oct 16, 2024
2 parents a0ae549 + 70935c9 commit 52c07c1
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 24 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,19 @@ Additionally, need to enable google drive api to use sheet sharing functionality
* **username:** User handle of requested user.
* **date:** "YYYY-MM" format date.
#### **`/delete-all-data`**
**Description:** Deletes all data between specific dates
**Usage:**
`/delete-all-data from: <from> until: <until>`
* **from:** "YYYY-MM-DD"
* **until:** "YYYY-MM-DD"
After using this command, there will be a modal to confirm the deletion process. In order to confirm the deletion, you need to enter your discord username and exact same dates with the command. **Warning** : This process cannot be reverted.
--------------
Expand Down
26 changes: 26 additions & 0 deletions github_tracker_bot/bot_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,32 @@ async def process_commit_day(username, repo_link, commits_day, commits_data):
return None


async def delete_all_data(since_date, until_date):
try:
deleted_users, updated_users = (
mongo_manager.delete_ai_decisions_and_clean_users(since_date, until_date)
)
if deleted_users is None:
deleted_users = []
if updated_users is None:
updated_users = []
logger.info(f"deleted_users: {str(deleted_users)}")
logger.info(f"updated_users: {str(updated_users)}")
all_users_to_be_updated = list(set(deleted_users + updated_users))
logger.info(f"all_users_to_be_updated: {str(all_users_to_be_updated)}")
for user in all_users_to_be_updated:
try:
mongo_manager.update_all_contribution_datas_from_ai_decisions(
user_handle=user
)
except Exception as e:
logger.error(
f"An error occurred while updating contribution fields for user: {user}: {e}"
)
except Exception as e:
logger.error(f"An error occurred while deleting data: {e}")


def convert_to_dict(data):
if isinstance(data, list):
return [convert_to_dict(item) for item in data]
Expand Down
133 changes: 111 additions & 22 deletions github_tracker_bot/mongo_data_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,12 @@ def update_all_contribution_datas_from_ai_decisions(

try:
user = self.get_user(user_handle)
if user is None:
logger.error(
f"User with handle {user_handle} cannot be updated because it does not exist."
)
return None

ai_decisions = user.ai_decisions

calculated_data = count_all_contribution_data(ai_decisions)
Expand Down Expand Up @@ -554,26 +560,109 @@ def set_qualified_daily_contribution_streak(
raise

def update_ai_decisions(self, user: User, new_decisions: List[AIDecision]) -> None:
logger.info(f"Updating AI decisions for user {user.user_handle}")
logger.info(f"New decisions: {new_decisions}")
logger.info(f"Old decisions: {user.ai_decisions}")
if len(user.ai_decisions) == 0:
user.ai_decisions = [new_decisions]
else:
for new_decision in new_decisions:
for user_ai_decision in user.ai_decisions[0]:
if (
user_ai_decision.repository == new_decision.repository
and user_ai_decision.date == new_decision.date
):
user_ai_decision.response = new_decision.response
for commit in new_decision.commit_hashes:
if commit not in user_ai_decision.commit_hashes:
user_commit_hashes = user_ai_decision.commit_hashes
if type(user_commit_hashes) != list:
user_commit_hashes = user_commit_hashes.split(",")
user_commit_hashes.extend(commit)
user_ai_decision.commit_hashes = user_commit_hashes
break
for new_decision in new_decisions:
if user.ai_decisions == None or user.ai_decisions == []:
user.ai_decisions = [[]]
user.ai_decisions[0].extend([new_decision])
continue
for user_ai_decision in user.ai_decisions[0]:
if (
user_ai_decision.repository == new_decision.repository
and user_ai_decision.date == new_decision.date
):
user_ai_decision.response = new_decision.response
for commit in new_decision.commit_hashes:
if commit not in user_ai_decision.commit_hashes:
user_commit_hashes = user_ai_decision.commit_hashes
if type(user_commit_hashes) != list:
user_commit_hashes = user_commit_hashes.split(",")
user_commit_hashes.extend(commit)
user_ai_decision.commit_hashes = user_commit_hashes
break
else:
user.ai_decisions[0].extend([new_decision])

from datetime import datetime

def find_users_with_ai_decisions_in_date_range(
self, since_date: str, until_date: str
) -> List[Dict]:
"""Find users with any ai_decisions between the specified dates."""
try:
since_dt = datetime.strptime(since_date, "%Y-%m-%d")
until_dt = datetime.strptime(until_date, "%Y-%m-%d")

users = self.collection.find(
{
"ai_decisions": {
"$elemMatch": {
"$elemMatch": {
"date": {
"$gte": since_dt.strftime("%Y-%m-%d"),
"$lte": until_dt.strftime("%Y-%m-%d"),
}
}
}
}
}
)
return list(users)
except Exception as e:
logger.error(f"Failed to find users with ai_decisions in date range: {e}")
raise

def delete_ai_decisions_and_clean_users(
self, since_date: str, until_date: str
) -> int:
"""Deletes ai_decisions between dates, and deletes user if no ai_decisions remain."""
try:
since_dt = datetime.strptime(since_date, "%Y-%m-%d")
until_dt = datetime.strptime(until_date, "%Y-%m-%d")

users_to_update = self.find_users_with_ai_decisions_in_date_range(
since_date, until_date
)

deleted_users = []
updated_users = []

for user in users_to_update:
user_handle = user["user_handle"]
updated_ai_decisions = []

for decision_list in user["ai_decisions"]:
new_decision_list = [
decision
for decision in decision_list
if not (
since_dt
<= datetime.strptime(decision["date"], "%Y-%m-%d")
<= until_dt
)
]
if new_decision_list:
updated_ai_decisions.append(new_decision_list)

if not updated_ai_decisions:
self.collection.delete_one({"user_handle": user_handle})
logger.info(
f"Deleted user {user_handle} because all ai_decisions were removed."
)
deleted_users.extend([user_handle])
else:
user.ai_decisions[0].extend([new_decision])
self.collection.update_one(
{"user_handle": user_handle},
{"$set": {"ai_decisions": updated_ai_decisions}},
)
logger.info(f"Updated user {user_handle} with new ai_decisions.")
updated_users.extend([user_handle])

logger.info(
f"Deleted {len(deleted_users)} users and updated {len(updated_users)} users."
)
return deleted_users, updated_users
except Exception as e:
logger.error(
f"Failed to delete ai_decisions and clean users between {since_date} and {until_date}: {e}"
)
raise
19 changes: 18 additions & 1 deletion leader_bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
get_ai_decisions_by_user_and_timeframe,
calculate_monthly_streak,
)
from modals import UserModal
from modals import UserModal, UserDeletionModal
from helpers import csv_to_structured_string
import utils

Expand Down Expand Up @@ -634,4 +634,21 @@ async def on_command(interaction: discord.Interaction, username: str, date: str)
await interaction.followup.send(f"An error occurred: {e}", ephemeral=True)


@tree.command(
name="delete-all-data",
description="Deletes all data between specific dates.",
guild=discord.Object(id=config.GUILD_ID),
)
async def on_command(interaction: discord.Interaction, from_date: str, until_date: str):
try:
modal = UserDeletionModal(from_date=from_date, until_date=until_date)
await interaction.response.send_modal(modal)

except Exception as e:
logger.error(f"Error in on_command: {e}")
await interaction.followup.send(
"Something went wrong while processing the command.", ephemeral=True
)


client.run(config.DISCORD_TOKEN)
62 changes: 62 additions & 0 deletions leader_bot/modals.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import json

from datetime import datetime
from github_tracker_bot.bot_functions import delete_all_data

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

Expand Down Expand Up @@ -98,3 +99,64 @@ async def on_error(
) -> None:
logger.error(f"Error in on_error: {error}")
await interaction.followup.send("Oops! Something went wrong.", ephemeral=True)


class UserDeletionModal(Modal, title="User Deletion"):
def __init__(self, from_date: str = "", until_date: str = ""):
super().__init__(title="User Deletion")

self.initial_from_date = from_date
self.initial_until_date = until_date

self.discord_handle = TextInput( ##TODO: clarify github or discord username
label="Discord Handle",
placeholder="Enter your Discord handle",
)
self.from_date = TextInput(
label="From Date (YYYY-MM-DD)",
placeholder="Enter the start date",
)
self.until_date = TextInput(
label="Until Date (YYYY-MM-DD)",
placeholder="Enter the end date",
)

self.add_item(self.discord_handle)
self.add_item(self.from_date)
self.add_item(self.until_date)

async def on_submit(self, interaction: discord.Interaction):
await interaction.response.defer()

try:
discord_handle = self.discord_handle.value.strip()
modal_from_date = self.from_date.value.strip()
modal_until_date = self.until_date.value.strip()

if (
self.initial_from_date != modal_from_date
or self.initial_until_date != modal_until_date
):
await interaction.followup.send(
"Dates do not match. Please try again.", ephemeral=True
)
return

elif self.initial_until_date < self.initial_from_date:
await interaction.followup.send(
"Until date shouldn't be fewer than From date. Please try again.",
ephemeral=True,
)
return

await delete_all_data(modal_from_date, modal_until_date)

await interaction.followup.send(
f"All data between {modal_from_date} and {modal_until_date} has been deleted.",
ephemeral=True,
)
except Exception as e:
logger.error(f"Error in on_submit: {e}")
await interaction.followup.send(
"Oops! Something went wrong.", ephemeral=True
)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

setup(
name="pgt_leaderbot",
version="0.3.7",
version="0.4.0",
packages=find_packages(),
)

0 comments on commit 52c07c1

Please sign in to comment.