Skip to content

Commit

Permalink
Merge branch 'main' into feat/HelloAssoProtocol
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasThePatator committed Nov 27, 2024
2 parents ace1134 + 9deea91 commit dbeb06c
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 18 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,4 @@ cython_debug/
#.idea/
.vscode/*
client_secrets.json
thalosdiscordbot-eb19ad40416e.json
2 changes: 1 addition & 1 deletion src/SilicaAnimus/discord_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ async def give_role(self, ctx, *args, **kwargs):
raise

roles_stack = args[:split_rank]
user_stack = args[(split_rank + 1):]
user_stack = args[split_rank + 1:]

# Running command
for role, g_user in itt.product(roles_stack, user_stack):
Expand Down
143 changes: 136 additions & 7 deletions src/SilicaAnimus/google_sheets_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@
from dataclasses import dataclass
import logging

from typing import Union
from typing import List


@dataclass
class MemberInfo:
first_name: str = ""
last_name: str = ""
discord_nickname: str = ""
server_nickname: str = ""
in_spreadsheet: bool = False
member_current_year: bool = False
member_last_year: bool = False


class GoogleSheetsClient:
Expand All @@ -34,7 +35,7 @@ def __init__(self, clients_secrets_path: str):
self.sheets = self.google_service.spreadsheets()
self.logger.info("Succesfully logged into Gsheet API")

async def get_spreadsheet(self) -> Union[None, ResourceWarning]:
async def get_spreadsheet(self):
"""Returns the spreadsheet
Returns:
Expand Down Expand Up @@ -89,6 +90,9 @@ async def get_member_by_discord_name(self, discord_name: str) -> MemberInfo:
"""Get the member's information using the discord name
Args:
discord_name (str): discord name of the user
Returns:
MemberInfo : The member's information from the spreadsheet
"""

self.logger.info(f"Looking up user {discord_name}")
Expand All @@ -109,10 +113,54 @@ async def get_member_by_discord_name(self, discord_name: str) -> MemberInfo:
member_info.last_name = values[row_index][0]
member_info.first_name = values[row_index][1]
member_info.server_nickname = values[row_index][2]

return member_info

return member_info

async def get_members_by_discord_names(
self, discord_names: List[str]
) -> List[MemberInfo]:
"""Get the members' information using the discord name
Args:
discord_names (List[str]): discord names of the users to query
Returns:
List[MemberInfo] : The members' information from the spreadsheet
"""

self.logger.info(f"Looking up {len(discord_names)} users")

ss = await self.get_spreadsheet()
if ss is None:
return None

values = ss.get("values", [])

members_list = []

for row_index in range(len(values)):
if len(values[row_index]) < 3:
continue

if values[row_index][2] in discord_names:
member_info = MemberInfo()
member_info.discord_nickname = values[row_index][2]
member_info.in_spreadsheet = True
member_info.last_name = values[row_index][0]
member_info.first_name = values[row_index][1]
if len(values[row_index]) < 4:
continue
member_info.member_last_year = values[row_index][3] == "Oui"
if len(values[row_index]) < 5:
continue
member_info.member_current_year = values[row_index][4] == "Oui"

members_list.append(member_info)

return members_list

async def add_member(self, member_info: MemberInfo) -> bool:
"""Add the member in the spreadsheet. If the member is already in the spreadsheet, update informations about the member.
Expand All @@ -122,15 +170,20 @@ async def add_member(self, member_info: MemberInfo) -> bool:

self.logger.info(f"Adding {member_info.first_name} {member_info.last_name}")

values = (await self.get_spreadsheet()).get("values", [])
ss = await self.get_spreadsheet()
if ss is None:
return False

values = ss.get("values", [])

body = {
"values": [
[
member_info.last_name,
member_info.first_name,
member_info.server_nickname,
member_info.discord_nickname,
"Oui" if member_info.member_current_year else "",
"Oui" if member_info.member_last_year else "",
]
]
}
Expand All @@ -150,7 +203,7 @@ async def add_member(self, member_info: MemberInfo) -> bool:
self.sheets.values()
.append(
spreadsheetId=getenv("GOOGLE_SPREADSHEET_ID"),
range="A1",
range=f"{getenv("GOOGLE_SHEET_ID")}!A1",
valueInputOption="USER_ENTERED",
body=body,
)
Expand All @@ -168,12 +221,88 @@ async def add_member(self, member_info: MemberInfo) -> bool:
self.sheets.values()
.update(
spreadsheetId=getenv("GOOGLE_SPREADSHEET_ID"),
range=f"A{member_sheet_row}:F{member_sheet_row}",
range=f"{getenv("GOOGLE_SHEET_ID")}!A{member_sheet_row}:F{member_sheet_row}",
valueInputOption="USER_ENTERED",
body=body,
)
.execute()
)
except HttpError as error:
self.logger.error(error.content)
return None

return True

async def add_members(self, members_info: List[MemberInfo]) -> bool:
"""Add the members in the spreadsheet. If a member is already in the spreadsheet, update informations about the member.
Args:
member_info (List[MemberInfo]): The member's information.
"""

self.logger.info(f"Adding {len(members_info)} members")

ss = await self.get_spreadsheet()
if ss is None:
return False

values = ss.get("values", [])

insert_values = {
(member_info.first_name.lower(), member_info.last_name.lower()): [
member_info.last_name,
member_info.first_name,
member_info.discord_nickname,
"Oui" if member_info.member_current_year else "",
"Oui" if member_info.member_last_year else "",
]
for member_info in members_info
}

names_list = [(value[1].lower(), value[0].lower()) for value in values]

update_data = []
append_data = []

for member_info in members_info:
name_tuple = (member_info.first_name.lower(), member_info.last_name.lower())
if names_list.count(name_tuple) > 0:
member_sheet_row = names_list.index(name_tuple) + 1
update_data.append(
{
"range": f"{getenv("GOOGLE_SHEET_ID")}!A{member_sheet_row}:F{member_sheet_row}",
"values": [insert_values[name_tuple]],
}
)
else:
append_data.append(insert_values[name_tuple])

try:
self.logger.info(f"Updating {len(update_data)} existing members")
body = {"valueInputOption": "USER_ENTERED", "data": update_data}
(
self.sheets.values()
.batchUpdate(spreadsheetId=getenv("GOOGLE_SPREADSHEET_ID"), body=body)
.execute()
)
except HttpError as error:
self.logger.error(error.content)
return None

try:
self.logger.info(f"Appending {len(append_data)} new members")
body = {"values": append_data}
(
self.sheets.values()
.append(
spreadsheetId=getenv("GOOGLE_SPREADSHEET_ID"),
range=f"{getenv("GOOGLE_SHEET_ID")}!A1",
valueInputOption="USER_ENTERED",
body=body,
)
.execute()
)

except HttpError as error:
self.logger.error(error.content)
return None
Expand Down
29 changes: 21 additions & 8 deletions src/SilicaAnimus/helloasso_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,11 @@ async def refresh_access_token(self) -> bool:
self.logger.info("Access token refreshed")
return True

def make_membership_request(self, name_filter: Union[str, None] = None, continuationToken: Union[str, None] = None) -> request.Request:
def make_membership_request(
self,
name_filter: Union[str, None] = None,
continuationToken: Union[str, None] = None,
) -> request.Request:
members_request_data = parse.urlencode(
{
"organizationSlug": getenv("HELLOASSO_ORGANIZATIONSLUG"),
Expand All @@ -127,10 +131,12 @@ def make_membership_request(self, name_filter: Union[str, None] = None, continua
)

members_request_data = members_request_data.encode()
request_url = f"{getenv('HELLOASSO_API_URL')}/organizations/{getenv('HELLOASSO_ORGANIZATIONSLUG')}/forms/membership/" \
+ f"{getenv("HELLOASSO_MEMBERSHIP_FORM_SLUG")}/orders" \
+ "?pageSize=20" \
+ "&withDetails=false"
request_url = (
f"{getenv('HELLOASSO_API_URL')}/organizations/{getenv('HELLOASSO_ORGANIZATIONSLUG')}/forms/membership/"
+ f"{getenv("HELLOASSO_MEMBERSHIP_FORM_SLUG")}/orders"
+ "?pageSize=20"
+ "&withDetails=false"
)

if name_filter is not None:
request_url += f"&userSearchKey={name_filter}"
Expand Down Expand Up @@ -192,7 +198,9 @@ async def get_membership(self, first_name: str, last_name: str) -> bool:

return False

async def get_memberships(self, names: List[Tuple[str, str]]) -> set[Tuple[str, str]]:
async def get_memberships(
self, names: List[Tuple[str, str]]
) -> set[Tuple[str, str]]:
"""Check if a person is a current member of the association
Args:
Expand Down Expand Up @@ -225,14 +233,19 @@ async def get_memberships(self, names: List[Tuple[str, str]]) -> set[Tuple[str,
continue

user = item["user"]
if ((user["firstName"].lower(), user["lastName"].lower()) in lowered_name_list):
if (
user["firstName"].lower(),
user["lastName"].lower(),
) in lowered_name_list:
return_set.add((user["firstName"], user["lastName"]))

if resp_data["pagination"]["totalCount"] == 0:
return return_set

continuationToken = resp_data["pagination"]["continuationToken"]
members_request = self.make_membership_request(continuationToken=continuationToken)
members_request = self.make_membership_request(
continuationToken=continuationToken
)

async def start(self) -> bool:
"""Starts the client"""
Expand Down
1 change: 1 addition & 0 deletions src/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies = [
"pytest",
"pytest-asyncio",
"pre-commit",
"google-api-python-client"
]

[project.scripts]
Expand Down
22 changes: 20 additions & 2 deletions src/tests/test_google_sheets_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,36 @@ async def test_google_sheets_get_member_by_name() -> bool:
print(await client.get_member_by_name(first_name="titi", last_name="tata"))


@pytest.mark.asyncio
async def test_google_sheets_get_members_by_discord_name() -> bool:
client = GoogleSheetsClient(getenv("GOOGLE_SERVICE_ACCOUNT_SECRETS_PATH"))
print(await client.get_members_by_discord_names([".endya", "lucasthepatator", "jeanpierrepernaud"]))


@pytest.mark.asyncio
async def test_google_sheets_add_member() -> bool:
client = GoogleSheetsClient(getenv("GOOGLE_SERVICE_ACCOUNT_SECRETS_PATH"))
member_info = MemberInfo("titi", "tata", "tata123", "tata124")
member_info = MemberInfo("titi", "tata", "tata123", False, True, False)
print(await client.add_member(member_info))
member_info = MemberInfo("tutu", "tata", "qsdsqd", "qsdfqf")
member_info = MemberInfo("tutu", "tata", "qsdsqd", False, False, True)
print(await client.add_member(member_info))


@pytest.mark.asyncio
async def test_google_sheets_add_members() -> bool:
client = GoogleSheetsClient(getenv("GOOGLE_SERVICE_ACCOUNT_SECRETS_PATH"))
members_info = [
MemberInfo("titi", "tata", "tata123", False, False, True),
MemberInfo("tutu", "toto", "totolebg", False, False, True),
]
print(await client.add_members(members_info))


if __name__ == "__main__":
setup_function(test_google_sheets_client_connection)
asyncio.run(test_google_sheets_client_connection())
asyncio.run(test_google_sheets_get_spreadsheet())
asyncio.run(test_google_sheets_get_member_by_name())
asyncio.run(test_google_sheets_get_members_by_discord_name())
asyncio.run(test_google_sheets_add_member())
asyncio.run(test_google_sheets_add_members())

0 comments on commit dbeb06c

Please sign in to comment.