-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
슬랙에서 멤버 DB 채우기 #20
슬랙에서 멤버 DB 채우기 #20
Changes from all commits
e46773d
0b87d89
64fd3e6
6f965da
7d146bd
2d831c7
617b863
5842907
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,3 +44,6 @@ node_modules | |
*.pickle | ||
.DS_Store | ||
/install-pyenv-win.ps1 | ||
|
||
*.json | ||
*.csv |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from pydantic_settings import BaseSettings, SettingsConfigDict | ||
|
||
from waffledotcom.src.secrets import AWSSecretManager | ||
from waffledotcom.src.settings import settings | ||
|
||
|
||
class SlackConfig(BaseSettings): | ||
token: str = "" | ||
|
||
model_config = SettingsConfigDict( | ||
case_sensitive=False, env_prefix="SLACK_", env_file=settings.env_files | ||
) | ||
|
||
def __init__(self, *args, **kwargs) -> None: | ||
super().__init__(*args, **kwargs) | ||
aws_secret = AWSSecretManager() | ||
if aws_secret.is_available(): | ||
self.token = aws_secret.get_secret("slack_token") | ||
|
||
|
||
slack_config = SlackConfig() |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,49 @@ | ||||||||||
import asyncio | ||||||||||
|
||||||||||
from fastapi import Depends | ||||||||||
from loguru import logger | ||||||||||
from slack_sdk import WebClient | ||||||||||
from slack_sdk.errors import SlackApiError | ||||||||||
|
||||||||||
from waffledotcom.src.apps.user.services import UserService | ||||||||||
from waffledotcom.src.batch.slack.config import slack_config | ||||||||||
from waffledotcom.src.batch.slack.schema import SlackMember | ||||||||||
from waffledotcom.src.utils.dependency_solver import DependencySolver | ||||||||||
|
||||||||||
|
||||||||||
async def create_users_from_slack(user_service: UserService = Depends()): | ||||||||||
client = WebClient(token=slack_config.token) | ||||||||||
data = client.users_list().data | ||||||||||
|
||||||||||
assert isinstance(data, dict) | ||||||||||
Comment on lines
+16
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3) 무조건 dict 인건가요? 맞으면 그냥 이렇게 한 줄로 어떤가요
Suggested change
P2) 만약 dict가 아닐 수도 있다면, assert 말고 적절한 에러를 던지고 이유를 로깅해주는 게 좋을 것 같아요 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||
|
||||||||||
if not data.get("ok", False): | ||||||||||
raise SlackApiError("Slack API Error", data) | ||||||||||
|
||||||||||
members_to_create = [] | ||||||||||
for member in data.get("members", []): | ||||||||||
if member["is_bot"] or member["deleted"] or member["id"] == "USLACKBOT": | ||||||||||
continue | ||||||||||
|
||||||||||
member = SlackMember(**member) | ||||||||||
if member.profile.phone is not None: | ||||||||||
phone = ( | ||||||||||
member.profile.phone.replace("-", "") | ||||||||||
.replace(" ", "") | ||||||||||
.replace("+82", "") | ||||||||||
) | ||||||||||
member.profile.phone = phone | ||||||||||
|
||||||||||
members_to_create.append(member) | ||||||||||
|
||||||||||
user_service.create_users_from_slack(members_to_create) | ||||||||||
logger.debug(f"Created {len(members_to_create)} users from slack") | ||||||||||
|
||||||||||
|
||||||||||
def main(): | ||||||||||
solver = DependencySolver() | ||||||||||
asyncio.run(solver.run(create_users_from_slack)) | ||||||||||
Comment on lines
+43
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3) 이 부분 잘 이해가 안 가는데... batch 면 일정 주기마다 돌아가는 거 아닌가요?? 일회성으로 실행하는 것처럼 보이는데 부연 설명 좀 부탁합니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 스크립트는 일회성으로 실행하는게 맞지 않을까요 |
||||||||||
|
||||||||||
|
||||||||||
if __name__ == "__main__": | ||||||||||
main() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from __future__ import annotations | ||
|
||
from pydantic import BaseModel | ||
|
||
|
||
class SlackMember(BaseModel): | ||
id: str | ||
real_name: str | None = None | ||
profile: SlackMemberProfile | ||
deleted: bool | ||
is_bot: bool | ||
is_email_confirmed: bool | None = None | ||
is_admin: bool | None = None | ||
|
||
|
||
class SlackMemberProfile(BaseModel): | ||
first_name: str | None = None | ||
last_name: str | None = None | ||
email: str | None = None | ||
phone: str | None = None | ||
image_192: str | None = None | ||
|
||
|
||
SlackMember.model_rebuild() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import waffledotcom.src.apps.team.models # noqa | ||
import waffledotcom.src.apps.user.models # noqa |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,15 +17,18 @@ class DBConfig(BaseSettings): | |
case_sensitive=False, env_prefix="DB_", env_file=settings.env_files | ||
) | ||
|
||
@property | ||
def url(self) -> str: | ||
def __init__(self, *args, **kwargs) -> None: | ||
super().__init__(*args, **kwargs) | ||
Comment on lines
+20
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거 근데,, 안해주면 에러가 떠요. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 로그
|
||
aws_secrets = AWSSecretManager() | ||
if aws_secrets.is_available(): | ||
self.username = aws_secrets.get_secret("db_username") | ||
self.password = quote_plus(aws_secrets.get_secret("db_password")) | ||
self.host = aws_secrets.get_secret("db_host") | ||
self.port = int(aws_secrets.get_secret("db_port")) | ||
self.name = aws_secrets.get_secret("db_name") | ||
|
||
@property | ||
def url(self) -> str: | ||
return ( | ||
f"mysql+mysqldb://{self.username}:{self.password}" | ||
f"@{self.host}:{self.port}/{self.name}" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
"""Initial Migration | ||
|
||
Revision ID: f2b7ce2c8874 | ||
Revises: | ||
Create Date: 2023-10-06 20:04:38.514945 | ||
|
||
""" | ||
import sqlalchemy as sa | ||
from alembic import op | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = "f2b7ce2c8874" | ||
down_revision = None | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade() -> None: | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.create_table( | ||
"position", | ||
sa.Column("id", sa.Integer(), nullable=False), | ||
sa.Column("name", sa.String(length=50), nullable=False), | ||
sa.PrimaryKeyConstraint("id"), | ||
sa.UniqueConstraint("name"), | ||
) | ||
op.create_table( | ||
"team", | ||
sa.Column("id", sa.Integer(), nullable=False), | ||
sa.Column("name", sa.String(length=30), nullable=False), | ||
sa.Column("introduction", sa.String(length=1000), nullable=True), | ||
sa.PrimaryKeyConstraint("id"), | ||
) | ||
op.create_table( | ||
"user", | ||
sa.Column("id", sa.Integer(), nullable=False), | ||
sa.Column("sso_id", sa.String(length=50), nullable=True), | ||
sa.Column("username", sa.String(length=50), nullable=True), | ||
sa.Column("image_url", sa.String(length=200), nullable=True), | ||
sa.Column("first_name", sa.String(length=30), nullable=False), | ||
sa.Column("last_name", sa.String(length=30), nullable=False), | ||
sa.Column("department", sa.String(length=50), nullable=True), | ||
sa.Column("college", sa.String(length=50), nullable=True), | ||
sa.Column("phone_number", sa.String(length=30), nullable=True), | ||
sa.Column("github_id", sa.String(length=50), nullable=True), | ||
sa.Column("github_email", sa.String(length=50), nullable=True), | ||
sa.Column("slack_id", sa.String(length=50), nullable=True), | ||
sa.Column("slack_email", sa.String(length=50), nullable=True), | ||
sa.Column("notion_email", sa.String(length=50), nullable=True), | ||
sa.Column("apple_email", sa.String(length=50), nullable=True), | ||
sa.Column("is_rookie", sa.Boolean(), nullable=False), | ||
sa.Column("is_member", sa.Boolean(), nullable=False), | ||
sa.Column("is_active", sa.Boolean(), nullable=False), | ||
sa.Column("is_admin", sa.Boolean(), nullable=False), | ||
sa.Column("introduction", sa.String(length=1000), nullable=True), | ||
sa.PrimaryKeyConstraint("id"), | ||
sa.UniqueConstraint("slack_id"), | ||
sa.UniqueConstraint("sso_id"), | ||
sa.UniqueConstraint("username"), | ||
) | ||
op.create_table( | ||
"position_user_association", | ||
sa.Column("position_id", sa.Integer(), nullable=False), | ||
sa.Column("user_id", sa.Integer(), nullable=False), | ||
sa.ForeignKeyConstraint( | ||
["position_id"], | ||
["position.id"], | ||
), | ||
sa.ForeignKeyConstraint( | ||
["user_id"], | ||
["user.id"], | ||
), | ||
sa.PrimaryKeyConstraint("position_id", "user_id"), | ||
) | ||
op.create_table( | ||
"sns_account", | ||
sa.Column("id", sa.Integer(), nullable=False), | ||
sa.Column("user_id", sa.Integer(), nullable=False), | ||
sa.Column("name", sa.String(length=30), nullable=False), | ||
sa.Column("url", sa.String(length=200), nullable=False), | ||
sa.ForeignKeyConstraint( | ||
["user_id"], | ||
["user.id"], | ||
), | ||
sa.PrimaryKeyConstraint("id"), | ||
) | ||
op.create_table( | ||
"team_user_association", | ||
sa.Column("team_id", sa.Integer(), nullable=False), | ||
sa.Column("user_id", sa.Integer(), nullable=False), | ||
sa.ForeignKeyConstraint( | ||
["team_id"], | ||
["team.id"], | ||
), | ||
sa.ForeignKeyConstraint( | ||
["user_id"], | ||
["user.id"], | ||
), | ||
sa.PrimaryKeyConstraint("team_id", "user_id"), | ||
) | ||
# ### end Alembic commands ### | ||
|
||
|
||
def downgrade() -> None: | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.drop_table("team_user_association") | ||
op.drop_table("sns_account") | ||
op.drop_table("position_user_association") | ||
op.drop_table("user") | ||
op.drop_table("team") | ||
op.drop_table("position") | ||
# ### end Alembic commands ### |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
"""Add generation field | ||
|
||
Revision ID: c8dea6766159 | ||
Revises: f2b7ce2c8874 | ||
Create Date: 2023-10-31 21:39:07.729126 | ||
|
||
""" | ||
import sqlalchemy as sa | ||
from alembic import op | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = "c8dea6766159" | ||
down_revision = "f2b7ce2c8874" | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade() -> None: | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.add_column("user", sa.Column("generation", sa.String(length=30), nullable=True)) | ||
# ### end Alembic commands ### | ||
|
||
|
||
def downgrade() -> None: | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.drop_column("user", "generation") | ||
# ### end Alembic commands ### |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2) 만약 dotenv 아예 안 쓸 거면 여기 지워도 되지 싶습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아예 안쓰는건 아니고,
.env.local
,.env.test
만 두려고 합니다