diff --git a/api/messages/messages_service.py b/api/messages/messages_service.py index 7b2fb2c..d749f05 100644 --- a/api/messages/messages_service.py +++ b/api/messages/messages_service.py @@ -1,8 +1,8 @@ from common.utils import safe_get_env_var from common.utils.slack import send_slack_audit, create_slack_channel, send_slack, invite_user_to_channel -from common.utils.firebase import get_hackathon_by_event_id, upsert_news, upsert_praise, get_github_contributions_for_user,get_volunteer_from_db_by_event, get_recent_praises, get_praises_by_user_id +from common.utils.firebase import get_hackathon_by_event_id, upsert_news, upsert_praise, get_github_contributions_for_user,get_volunteer_from_db_by_event, get_user_by_user_id, get_recent_praises, get_praises_by_user_id from common.utils.openai_api import generate_and_save_image_to_cdn -from common.utils.github import create_github_repo +from common.utils.github import create_github_repo, get_all_repos, validate_github_username from api.messages.message import Message from services.users_service import get_propel_user_details_by_id, get_slack_user_from_propel_user_id, get_user_from_slack_id, save_user import json @@ -325,6 +325,28 @@ def get_teams_list(id=None): return { "teams": results } +@limits(calls=2000, period=THIRTY_SECONDS) +@cached(cache=TTLCache(maxsize=100, ttl=600)) +def get_team(id): + logger.debug(f"get_team Start team_id={id}") + + if id is not None: + # Get by id + db = get_db() + doc = db.collection('teams').document(id).get() + if doc is None: + logger.info("get_team End (no results)") + return {} + else: + logger.info(f"get_team End (with result):{doc.to_dict()}") + return doc_to_json(docid=doc.id, doc=doc) + else: + return { + "team": {} + } + + + @limits(calls=20, period=ONE_MINUTE) def get_npo_list(word_length=30): logger.debug("NPO List Start") @@ -344,9 +366,13 @@ def get_npo_list(word_length=30): return { "nonprofits": results } def save_team(propel_user_id, json): - send_slack_audit(action="save_team", message="Saving", payload=json) - slack_user = get_slack_user_from_propel_user_id(propel_user_id) - slack_user_id = slack_user["sub"] + send_slack_audit(action="save_team", message="Saving", payload=json) + + email, user_id, last_login, profile_image, name, nickname = get_propel_user_details_by_id(propel_user_id) + slack_user_id = user_id + + root_slack_user_id = slack_user_id.replace("oauth2|slack|T1Q7936BH-","") + user = get_user_doc_reference(root_slack_user_id) db = get_db() # this connects to our Firestore database logger.debug("Team Save") @@ -354,78 +380,124 @@ def save_team(propel_user_id, json): logger.debug(json) doc_id = uuid.uuid1().hex # Generate a new team id - name = json["name"] + team_name = json["name"] + + - root_slack_user_id = slack_user_id.replace("oauth2|slack|T1Q7936BH-","") - event_id = json["eventId"] slack_channel = json["slackChannel"] - problem_statement_id = json["problemStatementId"] + + hackathon_event_id = json["eventId"] + problem_statement_id = json["problemStatementId"] if "problemStatementId" in json else None + nonprofit_id = json["nonprofitId"] if "nonprofitId" in json else None + github_username = json["githubUsername"] + if validate_github_username(github_username) == False: + return { + "message": "Error: Invalid GitHub Username - don't give us your email, just your username without the @ symbol." + } - #TODO: This is not the way - user = get_user_doc_reference(slack_user_id) - if user is None: - return + + #TODO: This is a hack, but get the nonprofit if provided, then get the first problem statement + nonprofit = None + nonprofit_name = "" + if nonprofit_id is not None: + logger.info(f"Nonprofit ID provided {nonprofit_id}") + nonprofit = get_single_npo(nonprofit_id)["nonprofits"] + nonprofit_name = nonprofit["name"] + logger.info(f"Nonprofit {nonprofit}") + # See if the nonprofit has a least 1 problem statement + if "problem_statements" in nonprofit and len(nonprofit["problem_statements"]) > 0: + problem_statement_id = nonprofit["problem_statements"][0] + logger.info(f"Problem Statement ID {problem_statement_id}") + else: + return { + "message": "Error: Nonprofit does not have any problem statements" + } + - problem_statement = get_problem_statement_from_id(problem_statement_id) - if problem_statement is None: - return + problem_statement = None + if problem_statement_id is not None: + problem_statement = get_problem_statement_from_id_old(problem_statement_id) + logger.info(f"Problem Statement {problem_statement}") - # Define vars for github repo creation - hackathon_event_id = get_single_hackathon_id(event_id)["event_id"] - team_name = name + if nonprofit is None and problem_statement is None: + return "Error: Please provide either a Nonprofit or a Problem Statement" + + team_slack_channel = slack_channel raw_problem_statement_title = problem_statement.get().to_dict()["title"] # Remove all spaces from problem_statement_title problem_statement_title = raw_problem_statement_title.replace(" ", "").replace("-", "") + logger.info(f"Problem Statement Title: {problem_statement_title}") - repository_name = f"{team_name}--{problem_statement_title}" + nonprofit_title = nonprofit_name.replace(" ", "").replace("-", "") + # Truncate nonprofit name to first 20 chars to support github limits + nonprofit_title = nonprofit_title[:20] + logger.info(f"Nonprofit Title: {nonprofit_title}") + + repository_name = f"{team_name}-{nonprofit_title}-{problem_statement_title}" + logger.info(f"Repository Name: {repository_name}") # truncate repostory name to first 100 chars to support github limits repository_name = repository_name[:100] + logger.info(f"Truncated Repository Name: {repository_name}") - slack_name_of_creator = user.get().to_dict()["name"] + slack_name_of_creator = name + nonprofit_url = f"https://ohack.dev/nonprofit/{nonprofit_id}" project_url = f"https://ohack.dev/project/{problem_statement_id}" # Create github repo try: - repo = create_github_repo(repository_name, hackathon_event_id, slack_name_of_creator, team_name, team_slack_channel, problem_statement_id, raw_problem_statement_title, github_username) + logger.info(f"Creating github repo {repository_name} for {json}") + repo = create_github_repo(repository_name, hackathon_event_id, slack_name_of_creator, team_name, team_slack_channel, problem_statement_id, raw_problem_statement_title, github_username, nonprofit_name, nonprofit_id) except ValueError as e: return { "message": f"Error: {e}" } logger.info(f"Created github repo {repo} for {json}") + logger.info(f"Creating slack channel {slack_channel}") create_slack_channel(slack_channel) + + logger.info(f"Inviting user {slack_user_id} to slack channel {slack_channel}") invite_user_to_channel(slack_user_id, slack_channel) # Add all Slack admins too slack_admins = ["UC31XTRT5", "UCQKX6LPR", "U035023T81Z", "UC31XTRT5", "UC2JW3T3K", "UPD90QV17", "U05PYC0LMHR"] for admin in slack_admins: + logger.info(f"Inviting admin {admin} to slack channel {slack_channel}") invite_user_to_channel(admin, slack_channel) # Send a slack message to the team channel slack_message = f''' -:astronaut-floss-dancedance: Team `{name}` | `#{team_slack_channel}` has been created in support of project `{raw_problem_statement_title}` {project_url} by <@{root_slack_user_id}>. - -Github repo: {repo['full_url']} -- All code should go here! -- Everything we build is for the public good and carries an MIT license - -Questions? join <#C01E5CGDQ74> or use <#C05TVU7HBML> or <#C05TZL13EUD> Slack channels. -:partyparrot: - -Your next steps: -1. Add everyone to your GitHub repo like this: https://opportunity-hack.slack.com/archives/C1Q6YHXQU/p1605657678139600 -2. Create your DevPost project https://youtu.be/vCa7QFFthfU?si=bzMQ91d8j3ZkOD03 - - ASU Students use https://opportunity-hack-2023-asu.devpost.com/ - - Everyone else use https://opportunity-hack-2023-virtual.devpost.com/ -3. Ask your nonprofit questions and bounce ideas off mentors! -4. Hack the night away! -5. Post any pics to your socials with `#ohack2023` and mention `@opportunityhack` -6. Track any volunteer hours - you are volunteering for a nonprofit! -7. After the hack, update your LinkedIn profile with your new skills and experience! +:rocket: Team *{team_name}* is ready for launch! :tada: + +*Channel:* #{team_slack_channel} +*Nonprofit:* <{nonprofit_url}|{nonprofit_name}> +*Project:* <{project_url}|{raw_problem_statement_title}> +*Created by:* <@{root_slack_user_id}> (add your other team members here) + +:github_parrot: *GitHub Repository:* {repo['full_url']} +All code goes here! Remember, we're building for the public good (MIT license). + +:question: *Need help?* +Join <#C01E5CGDQ74> or <#C07KYG3CECX> for questions and updates. + +:clipboard: *Next Steps:* +1. Add team to GitHub repo: +2. Create DevPost project: +3. Submit to +4. Study your nonprofit slides and software requirements doc and chat with mentors +5. Code, collaborate, and create! +6. Share your progress on the socials: `#ohack2024` @opportunityhack +7. +8. Post-hack: Update LinkedIn with your amazing experience! +9. Update for a chance to win prizes! +10. Follow the schedule at + + +Let's make a difference! :muscle: :heart: ''' send_slack(slack_message, slack_channel) send_slack(slack_message, "log-team-creation") @@ -439,7 +511,7 @@ def save_team(propel_user_id, json): "team_number" : -1, "users": [user], "problem_statements": [problem_statement], - "name": name, + "name": team_name, "slack_channel": slack_channel, "created": my_date.isoformat(), "active": "True", @@ -464,7 +536,8 @@ def save_team(propel_user_id, json): }, merge=True) # Get the hackathon (event) - add the team to the event - event_collection = db.collection("hackathons").document(event_id) + hackathon_db_id = get_hackathon_by_event_id(hackathon_event_id)["id"] + event_collection = db.collection("hackathons").document(hackathon_db_id) event_collection_dict = event_collection.get().to_dict() new_teams = [] @@ -477,7 +550,7 @@ def save_team(propel_user_id, json): }, merge=True) # Clear the cache - logger.info(f"Clearing cache for event_id={event_id} problem_statement_id={problem_statement_id} user_doc.id={user_doc.id} doc_id={doc_id}") + logger.info(f"Clearing cache for event_id={hackathon_db_id} problem_statement_id={problem_statement_id} user_doc.id={user_doc.id} doc_id={doc_id}") clear_cache() # get the team from get_teams_list @@ -485,7 +558,7 @@ def save_team(propel_user_id, json): return { - "message" : f"Saved Team and GitHub repo created. See your Slack channel #{slack_channel} for more details.", + "message" : f"Saved Team and GitHub repo created. See your Slack channel --> #{slack_channel} for more details.", "success" : True, "team": team, "user": { @@ -493,112 +566,147 @@ def save_team(propel_user_id, json): "profile_image": user_dict["profile_image"], } } - -def join_team(propel_user_id, json): - send_slack_audit(action="join_team", message="Adding", payload=json) - db = get_db() # this connects to our Firestore database - logger.debug("Join Team Start") +def get_github_repos(event_id): + return get_all_repos(event_id) + +def join_team(propel_user_id, json): logger.info(f"Join Team UserId: {propel_user_id} Json: {json}") + team_id = json["teamId"] + + db = get_db() + + # Get user ID once slack_user = get_slack_user_from_propel_user_id(propel_user_id) - userid = slack_user["sub"] + userid = get_user_from_slack_id(slack_user["sub"]).id - team_id = json["teamId"] + # Reference the team document + team_ref = db.collection('teams').document(team_id) + user_ref = db.collection('users').document(userid) - team_doc = db.collection('teams').document(team_id) - team_dict = team_doc.get().to_dict() + @firestore.transactional + def update_team_and_user(transaction): + # Read operations + team_doc = team_ref.get(transaction=transaction) + user_doc = user_ref.get(transaction=transaction) - user_doc = get_user_doc_reference(userid) - user_dict = user_doc.get().to_dict() - new_teams = [] - for t in user_dict["teams"]: - new_teams.append(t) - new_teams.append(team_doc) - user_doc.set({ - "teams": new_teams - }, merge=True) + if not team_doc.exists: + raise ValueError("Team not found") + if not user_doc.exists: + raise ValueError("User not found") - new_users = [] - if "users" in team_dict: - for u in team_dict["users"]: - new_users.append(u) - new_users.append(user_doc) + team_data = team_doc.to_dict() + user_data = user_doc.to_dict() - # Avoid any duplicate additions - new_users_set = set(new_users) + team_users = team_data.get("users", []) + user_teams = user_data.get("teams", []) - team_doc.set({ - "users": new_users_set - }, merge=True) + # Check if user is already in team + if user_ref in team_users: + logger.warning(f"User {userid} is already in team {team_id}") + return False + # Prepare updates + new_team_users = list(set(team_users + [user_ref])) + new_user_teams = list(set(user_teams + [team_ref])) - # Clear the cache - logger.info(f"Clearing cache for team_id={team_id} and user_doc.id={user_doc.id}") - clear_cache() + # Write operations + transaction.update(team_ref, {"users": new_team_users}) + transaction.update(user_ref, {"teams": new_user_teams}) - logger.debug("Join Team End") - return Message("Joined Team") + logger.debug(f"User {userid} added to team {team_id}") + return True + + # Execute the transaction + try: + transaction = db.transaction() + success = update_team_and_user(transaction) + if success: + send_slack_audit(action="join_team", message="Added", payload=json) + message = "Joined Team" + else: + message = "User was already in the team" + except Exception as e: + logger.error(f"Error in join_team: {str(e)}") + return Message(f"Error: {str(e)}") + # Clear caches + get_team.cache_clear() + get_user_by_id_old.cache_clear() + doc_to_json.cache_clear() + logger.debug("Join Team End") + return Message(message) def unjoin_team(propel_user_id, json): - send_slack_audit(action="unjoin_team", message="Removing", payload=json) - db = get_db() # this connects to our Firestore database - logger.debug("Unjoin Team Start") - logger.info(f"Unjoin for UserId: {propel_user_id} Json: {json}") team_id = json["teamId"] + db = get_db() + + # Get user ID once slack_user = get_slack_user_from_propel_user_id(propel_user_id) - userid = slack_user["sub"] + userid = get_user_from_slack_id(slack_user["sub"]).id - ## 1. Lookup Team, Remove User - doc = db.collection('teams').document(team_id) - - if doc: - doc_dict = doc.get().to_dict() - send_slack_audit(action="unjoin_team", - message="Removing", payload=doc_dict) - user_list = doc_dict["users"] if "users" in doc_dict else [] - - # Look up a team associated with this user and remove that team from their list of teams - new_users = [] - for u in user_list: - user_doc = u.get() - user_dict = user_doc.to_dict() - - new_teams = [] - if userid == user_dict["user_id"]: - for t in user_dict["teams"]: - logger.debug(t.get().id) - if t.get().id == team_id: - logger.debug("Remove team") - else: - logger.debug("Keep team") - new_teams.append(t) - else: - logger.debug("Keep user") - new_users.append(u) - # Update users collection with new teams - u.set({ - "teams": new_teams - }, merge=True) # merging allows to only update this column and not blank everything else out - - doc.set({ - "users": new_users - }, merge=True) - logger.debug(new_users) - - # Clear the cache - logger.info(f"Clearing team_id={team_id} cache") - clear_cache() - - logger.debug("Unjoin Team End") + # Reference the team document + team_ref = db.collection('teams').document(team_id) + user_ref = db.collection('users').document(userid) - return Message( - "Removed from Team") + @firestore.transactional + def update_team_and_user(transaction): + # Read operations + team_doc = team_ref.get(transaction=transaction) + user_doc = user_ref.get(transaction=transaction) + + if not team_doc.exists: + raise ValueError("Team not found") + if not user_doc.exists: + raise ValueError("User not found") + + team_data = team_doc.to_dict() + user_data = user_doc.to_dict() + + user_list = team_data.get("users", []) + user_teams = user_data.get("teams", []) + + # Check if user is in team + if user_ref not in user_list: + logger.warning(f"User {userid} not found in team {team_id}") + return False + + # Prepare updates + new_user_list = [u for u in user_list if u.id != userid] + new_user_teams = [t for t in user_teams if t.id != team_id] + + # Write operations + transaction.update(team_ref, {"users": new_user_list}) + transaction.update(user_ref, {"teams": new_user_teams}) + + logger.debug(f"User {userid} removed from team {team_id}") + return True + + # Execute the transaction + try: + transaction = db.transaction() + success = update_team_and_user(transaction) + if success: + send_slack_audit(action="unjoin_team", message="Removed", payload=json) + message = "Removed from Team" + else: + message = "User was not in the team" + except Exception as e: + logger.error(f"Error in unjoin_team: {str(e)}") + return Message(f"Error: {str(e)}") + + # Clear caches + get_team.cache_clear() + get_user_by_id_old.cache_clear() + doc_to_json.cache_clear() + + logger.debug("Unjoin Team End") + return Message(message) @limits(calls=100, period=ONE_MINUTE) def update_npo_application( application_id, json, propel_id): @@ -1965,6 +2073,8 @@ def save_profile_metadata_old(propel_id, json): "Saved Profile Metadata" ) + +@cached(cache=TTLCache(maxsize=100, ttl=600), key=hash_key) def get_user_by_id_old(id): # Log logger.debug(f"Get User By ID: {id}") @@ -1977,6 +2087,7 @@ def get_user_by_id_old(id): fields = ["name", "profile_image", "user_id", "nickname", "github"] # Check if the field is in the response first res = {k: res[k] for k in fields if k in res} + res["id"] = doc.id logger.debug(f"Get User By ID Result: {res}") diff --git a/api/messages/messages_views.py b/api/messages/messages_views.py index 7f330b0..7c3ec55 100644 --- a/api/messages/messages_views.py +++ b/api/messages/messages_views.py @@ -32,6 +32,7 @@ save_hackathon, update_hackathon_volunteers, get_teams_list, + get_team, save_team, unjoin_team, join_team, @@ -50,7 +51,8 @@ save_praise, save_feedback, get_user_feedback, - get_volunteer_by_event + get_volunteer_by_event, + get_github_repos ) logger = logging.getLogger("myapp") @@ -215,12 +217,13 @@ def get_teams(): # Get a single team by id @bp.route("/team/", methods=["GET"]) -def get_team(team_id): - return (get_teams_list(team_id)) +def get_team_api(team_id): + return (get_team(team_id)) + -@auth.require_user @bp.route("/team", methods=["POST"]) +@auth.require_user def add_team(): if auth_user and auth_user.user_id: return save_team(auth_user.user_id, request.get_json()) @@ -231,8 +234,7 @@ def add_team(): @bp.route("/team", methods=["DELETE"]) @auth.require_user -def remove_user_from_team(): - +def remove_user_from_team(): if auth_user and auth_user.user_id: return vars(unjoin_team(auth_user.user_id, request.get_json())) else: @@ -385,6 +387,11 @@ def save_profile(): def get_github_profile_api(username): return get_github_profile(username) + +@bp.route("/github-repos/", methods=["GET"]) +def get_github_repos(event_id): + return get_github_repos(event_id) + # Get user profile by user id @bp.route("/profile/", methods=["GET"]) def get_profile_by_id(id): diff --git a/common/utils/github.py b/common/utils/github.py index 05a08a1..6b3e84b 100644 --- a/common/utils/github.py +++ b/common/utils/github.py @@ -6,15 +6,18 @@ load_dotenv() -def create_github_repo(repository_name, hackathon_event_id, slack_name_of_creator, team_name, team_slack_channel, problem_statement_id, problem_statement_title, github_username): - if hackathon_event_id == "2023_fall": - org_name = "2023-opportunity-hack" +def create_github_repo(repository_name, hackathon_event_id, slack_name_of_creator, team_name, team_slack_channel, problem_statement_id, problem_statement_title, github_username, nonprofit_name, nonprofit_id): + if hackathon_event_id == "2024_fall": + org_name = "2024-Arizona-Opportunity-Hack" else: raise ValueError('Not supported hackathon event id') g = Github(os.getenv('GITHUB_TOKEN')) org = g.get_organization(org_name) + if does_repo_exist(repository_name, hackathon_event_id): + raise ValueError(f"Repository {repository_name} already exists") + # Catch GitHubException try: repo = org.create_repo(repository_name, private = False) @@ -22,7 +25,7 @@ def create_github_repo(repository_name, hackathon_event_id, slack_name_of_creato print(e) raise ValueError(e.data['message']) - github_admins = ["bmysoreshankar", "jotpowers", "nemathew", "pkakathkar", "vertex", "gregv", "mosesj1914", "ananay", "leonkoech", "axeljonson"] + github_admins = ["bmysoreshankar", "jotpowers", "nemathew", "pkakathkar", "vertex", "gregv", "mosesj1914", "ananay", "axeljonson"] if github_username is not None and github_username != "": github_admins.append(github_username) @@ -47,29 +50,66 @@ def create_github_repo(repository_name, hackathon_event_id, slack_name_of_creato path="README.md", message="Add README.md", content=f''' -# {hackathon_event_id} Hackathon -https://hack.ohack.dev -## Team -{team_name} - -## Slack Channel -`#`[{team_slack_channel}](https://opportunity-hack.slack.com/app_redirect?channel={team_slack_channel}) +# {hackathon_event_id} Hackathon Project -## Problem Statement -[{problem_statement_title}](https://ohack.dev/project/{problem_statement_id}) +## Quick Links +- [Hackathon Details](https://www.ohack.dev/hack/{hackathon_event_id}) +- [Team Slack Channel](https://opportunity-hack.slack.com/app_redirect?channel={team_slack_channel}) +- [Nonprofit Partner](https://ohack.dev/nonprofit/{nonprofit_id}) +- [Problem Statement](https://ohack.dev/project/{problem_statement_id}) ## Creator @{slack_name_of_creator} (on Slack) +## Team "{team_name}" +- [Team Member 1](GitHub profile link) +- [Team Member 2](GitHub profile link) +- [Team Member 3](GitHub profile link) + + +## Project Overview +Brief description of your project and its goals. + +## Tech Stack +- Frontend: +- Backend: +- Database: +- APIs: + + + +## Getting Started +Instructions on how to set up and run your project locally. + +```bash +# Example commands +git clone [your-repo-link] +cd [your-repo-name] +npm install +npm start +``` + + ## Your next steps -1. ✅ Add everyone to your GitHub repo like this: https://opportunity-hack.slack.com/archives/C1Q6YHXQU/p1605657678139600 -2. ✅ Create your DevPost project like this https://youtu.be/vCa7QFFthfU?si=bzMQ91d8j3ZkOD03 -3. ✅ ASU Students use https://opportunity-hack-2023-asu.devpost.com/ -4. ✅ Everyone else use https://opportunity-hack-2023-virtual.devpost.com/ -5. ✅ Your DevPost final submission demo video should be 3 minutes or less -6. ✅ Review the judging criteria on DevPost +1. ✅ Add everyone on your team to your GitHub repo like [this video posted in our Slack channel](https://opportunity-hack.slack.com/archives/C1Q6YHXQU/p1605657678139600) +2. ✅ Create your DevPost project [like this video](https://youtu.be/vCa7QFFthfU?si=bzMQ91d8j3ZkOD03) +3. ✅ Use the [2024 DevPost](https://opportunity-hack-2024-arizona.devpost.com) to submit your project +4. ✅ Your DevPost final submission demo video should be 4 minutes or less +5. ✅ Review the judging criteria on DevPost # What should your final Readme look like? +Your readme should be a one-stop-shop for the judges to understand your project. It should include: +- Team name +- Team members +- Slack channel +- Problem statement +- Tech stack +- Link to your DevPost project +- Link to your final demo video +- Any other information you think is important + +You'll use this repo as your resume in the future, so make it shine! 🌟 + Examples of stellar readmes: - ✨ [2019 Team 3](https://github.com/2019-Arizona-Opportunity-Hack/Team-3) - ✨ [2019 Team 6](https://github.com/2019-Arizona-Opportunity-Hack/Team-6) @@ -88,3 +128,52 @@ def create_github_repo(repository_name, hackathon_event_id, slack_name_of_creato "repo_name": repo.name, "full_url": f"https://github.com/{org_name}/{repo.name}" } + + +def does_repo_exist(repo_name, hackathon_event_id): + if hackathon_event_id == "2024_fall": + org_name = "2024-Arizona-Opportunity-Hack" + else: + raise ValueError('Not supported hackathon event id') + + g = Github(os.getenv('GITHUB_TOKEN')) + org = g.get_organization(org_name) + try: + repo = org.get_repo(repo_name) + return True + except GithubException as e: + print(e) + return False + + +def validate_github_username(github_username): + g = Github(os.getenv('GITHUB_TOKEN')) + try: + user = g.get_user(github_username) + return True + except GithubException as e: + print(e) + return False + + + +def get_all_repos(hackathon_event_id): + if hackathon_event_id == "2024_fall": + org_name = "2024-Arizona-Opportunity-Hack" + else: + raise ValueError('Not supported hackathon event id') + + g = Github(os.getenv('GITHUB_TOKEN')) + org = g.get_organization(org_name) + repos = org.get_repos() + + repo_list = [] + for repo in repos: + repo_list.append({ + "repo_name": repo.name, + "full_url": f"{repo.html_url}", + "description": repo.description, + "owners": [owner.login for owner in repo.get_collaborators()], + "created_at": repo.created_at, + "updated_at": repo.updated_at + }) diff --git a/common/utils/slack.py b/common/utils/slack.py index e29ee20..dc85a4e 100644 --- a/common/utils/slack.py +++ b/common/utils/slack.py @@ -3,6 +3,7 @@ import datetime, json from ratelimiter import RateLimiter from slack_sdk import WebClient +from slack_sdk.models.blocks import SectionBlock from slack_sdk.errors import SlackApiError from dotenv import load_dotenv from requests.exceptions import ConnectionError @@ -167,21 +168,23 @@ def send_slack(message="", channel="", icon_emoji=None, username="Hackathon Bot" if channel_id is None: logger.warning("Unable to get channel id from name, might be a user?") channel_id = channel - - # Joining isn't necessary to be able to send messages via chat_postMessage - #join_result = client.conversations_join(channel=channel_id) - # print(join_result) - - # Post + logger.info("Sending message...") try: response = client.chat_postMessage( channel=channel_id, - text=message, + blocks=[ + SectionBlock( + text={ + "type": "mrkdwn", + "text": message + } + ) + ], username=username, - icon_emoji=icon_emoji) + icon_emoji=icon_emoji + ) except SlackApiError as e: - # You will get a SlackApiError if "ok" is False logger.error(e.response["error"]) assert e.response["error"]