Giter Club home page Giter Club logo

jubilant-train's Introduction

jubilant-train's People

Contributors

viiviii avatar

Watchers

 avatar

jubilant-train's Issues

전체 테스트 실행 시 테스트가 실패한다

문제

  • 하나의 테스트 실행은 성공하지만 전체 테스트를 실행할 경우 테스트가 실패한다

이유

  • 현재 드라이버를 하나로 쓰고 있기 때문이다

이에 따라

  • 테스트가 실행 순서에 의존적이다
  • 메서드마다 url을 새로 이동하도록 구현했지만 제대로 동작하지 않게 된다
    • ex) 이미 로그인이 된 브라우저는 로그인 페이지로 이동되지 않음

개선

  • 연관된 테스트를 클래스 별로 그룹화한다
    • 테스트가 격리되어 클래스 별로 드라이버 생명주기 싸이클을 가진다
    • 클래스 내부에서는 메서드 실행 순서에 의존하여 중복 코드를 제외한다

기타

  • 드라이버를 사용하는 이 테스트는 단위 테스트라가 아니라서 메서드 별로 테스트를 격리할 필요는 없다고 생각함
  • 드라이버를 생성하고 종료시키는 것 자체가 테스트 속도를 꽤 잡아먹는다

목표 기능을 정리한다

image

이미 난 1등 당첨 시 연차 핑계까지 모든 준비가 완료됐다

  • 발생한 문제: 백수라 연차 못냄, 로또 당첨 안됨, 로또 사지도 않았음

목표

  • 오랫동안 로또 자동화를 실현한다

필요한 기능

  • 로그인
  • 구매
  • 당첨확인
  • 알림
    • 당첨 결과
    • 실패
    • 로그인
    • 구매

구현할 기능

  • 복권을 구매한다(자동, 갯수)
  • 당첨 결과를 확인한다
  • 결과를 전송한다
    • 당첨 결과

어떻게

  • 스크래핑
    • 언어: Python
    • 라이브러리: Selenium
  • 스케줄링: Git Actions
  • 알림: Git Issues -> 메일

기타

  • 알림은 귀찮으니까 최소로 해야 한다
    • 잔액은 당첨 결과 메세지에 함께 보여주자
  • 로또 당첨 결과 확인 시 로그인 이유 - 구매한 번호 저장, 당첨결과 비교 등을 구현하기 귀찮음

예외 처리 및 메시지 출력

  • 로그인 실패
  • 구매 실패(잔액 부족 등)

  • 해당 사이트에서 메시지를 주지만 현재 아직 결과로 출력하고 있지 않음
  • 값 validate 미존재

[제목]
🚨 로또 구매 실패(23-02-16)

[내용]
상세 내용: 구매시 오류가 발생하였습니다. 오류메시지:[예치금] 초과되었습니다. 초과구매액: 5000
발생 시각: 2023-02-16 17:28:12.054154

패키지가 이상해

문제

  • 역시 이번 프로젝트도 패키지들을 제대로 묶지 못하고 방황하고 있다😭
  • 특히 result 패키지가 이상하다
    • composite action으로 구현했을 땐 액션 이름이 패키지 이름이라 좀 참을만 했는데 이번에 action.yml이 사라지면서 진짜 이상해졌음
  • 그래서 거의 동일한 buy workflow를 만들기 싫음ㅠ

반성해

  • 잠깐 예전에 공부했던 걸 봐보니 액터를 잘 안나눈 것 같다
  • 플젝 처음 시작할 때 엔드포인트를 고민 안해보고 나중에 정해야지~한게 문제 같음
  • 사실 고수였다면 세부사항(local, cloud, git action) 결정을 미룰 수 있게 잘 나눴겠지만 고수도 아니면서 고민조차 안해봤음🔫💥

아마도

def inputs():
return env.to_account()
def outputs(search_dates: DateRange, table: Table) -> None:
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
print(f'search-dates={search_dates.as_dict()}', file=fh)
print(f'summary={asdict(Summary.from_table(table))}', file=fh)
_output_multiline_value('table', markdown.from_table(table), file=fh)

  • ✅ result의 main은 github action의 input, output에 관한 것만 관심 있어야될 것 같다
    • 그리고 env 파일이 마음에 안들었는데 이걸 잘 옮기면 더 관련된 파일에 둘 수 있지 않을까?

def latest_result(lotto: Lotto, account: Account) -> None:
latest_dates = latest()
lotto.login(account)
buys = lotto.result(dates=latest_dates)
outputs(search_dates=latest_dates, table=buys)

  • 😵여기가 이상함

Git actions로 일정에 따라 스크립트를 동작시킨다

목표

Git actions로 구매, 당첨 확인을 지정한 날짜에 실행시키고 이메일로 알림을 받는다

TODO

  • 구매 - 매주 평일(주 5회)
  • 확인 - 매주 일요일(주 1회)

위와 같이 결정한 이유

  • 구매
    • 로또는 온라인에서 매주 5천원까지만 살 수 있다
    • 로또는 매일 6시부터 24시까지 구매 가능하다(추첨일 예외)
  • 확인
    • 로또 추첨 당일인 오후 8시 30분부터 일정 시간까진 웹 사이트에서 내 구매 결과를 바로 확인할 수 없다
      • 내가 확인했을 땐 23시 50분까지도 결과 반영중이라고 뜸
    • 구매 번호를 어딘가에 저장해서 매칭하면 로그인 없이 바로 확인 가능하다
    • 난 굳이 바로 알고싶진 않아서 일요일에 확인함

작업

  • 실행 - git action으로 Private repository에서 스케쥴링 등록
  • 알림 - git issue로 결과 조회를 출력하고 git 알림 기능으로 해당 계정 이메일로 알림 받음

결과 조회를 개선한다

문제

  • reusable actions에 대해 알아보니 schedule은 caller측에서 지정해야 했다.
  • 난 called측에서 제공할 수 있을거라 생각하여 날짜 범위를 직전 회차의 일주일로 개발했으나 이 부분을 수정하는게 쓰기 편할 것 같다.

고민한 부분

결과 조회, 기간을 어떻게 제공할지

  • Case A: 시작일, 종료일 날짜를 사용자가 직접 지정
  • Case B: 오늘, 일주일, 한달 3가지 옵션으로 제공
  • Case C: 직전 회차 조회

고민 이유

  • 날짜 입력 시 git actitons yml은 리눅스 + actions 명령어를 알아야하므로 기존 코드에 비해 사용자가 사용하기 쉽지 않다

결정

사용자가 편한 것으로 제공해라

  • 내가 계속 고민된 이유는 어중간해서였던 것 같다
    • 편하게 제공할거면 [직전 회차 조회]로 제공하는게 낫다

변경 및 개선할 부분

  • 직전 회차 조회
    • 이전 판매일 시작, 종료일인 일요일~토요일까지를 조회한다
  • 조회 결과는 예전처럼 Table로 리턴
    • 그러면 조회 결과가 없는건 메세지로 보여주든 예외를 던지든 클라이언트 코드에서 결정할 수 있다

중간에 바꾼 부분

  • 조회 기간 직접 입력 기능 제거
    • 이유는 동행복권 사이트의 페이징 사이즈가 10이라 한달이면 2번의 API를 호출해야된다
    • 1년이면 48번, 10년이면 480번인데 내 서버도 아닌데 너무 막 호출하는 것 같아서 제거했음

프로젝트를 세팅한다

프로젝트

  • python 3.9
  • selenium 4.8.0
  • pytest 7.2.1

기타

  • pytest.ini 추가
  • Pylint 플러그인 설치
  • PyCharm 설정 - Actions on Save

소스 코드에서 로그인 계정 정보를 제거한다

문제

  • 현재 계정 정보가 하드코딩 되어 있음

jubilant-train/main.py

Lines 49 to 52 in 71dbd66

if __name__ == '__main__':
# todo: 개인정보인데 어떻게 관리?
_id = 'my_id'
_password = 'my_password'

방안

🤖ChatGPT의 제안은 아래와 같음

  1. 설정 파일 사용
  2. 환경변수 사용
  3. 암호화된 키를 사용(Key Management System)

방식 (1)은 구현이 쉽다는 장점이 있지만, 비밀번호가 파일에 평문으로 저장된다는 부분이 가장 별로임
그리고 해당 파일의 위치가 소스 코드에 적혀있으므로 내 노트북이 켜져있을 때 물리로 탈취 가능한 부분이 아닌가?

방식 (2)도 비밀번호가 평문으로 저장되고 터미널에서 언제든 확인할 수 있음
특히 비밀번호가 흩어져서 관리되는 느낌이라 별로임 (내가 잘 까먹으니까ㅎㅎㅋ)

난 아래의 2가지라도 만족하는 방식을 원함

  • 일반적인 파일에 저장하지 않았으면 좋겠음
  • 시각적으로 비밀번호를 바로 확인할 수 없어야 함
  • 비밀번호 관리하는 곳이 해당 프로그램이거나 기존 시스템이어야 함

로또 구매 기능을 구현한다

구현할 기능

정상

  • 로그인 페이지로 이동한다
  • 계정으로 로그인한다
  • 로또 구매 페이지로 이동한다
  • 옵션을 선택한다 (자동, 수량)
  • 로또를 구매한다

예외

  • 로그인이 실패하면 예외를 던진다
  • 로또 구매에 실패하면 예외를 던진다

결과를 전송한다

구현할 기능

  • 결과를 전송한다
    • 당첨 결과
    • 예외 - 로그인 실패, 구매 실패(잔액 부족 등)

메세지 형식

당첨 결과

[제목]
🎊 로또6/45 1055회(23-02-18)

[내용]
💰 총 당첨금: 1,234,567원
✅ 총 구입매수: 5장
📅 조회기간: 23-02-12 ~ 23-02-18

예외

[제목]
🚨 로또 구매 실패(23-02-16)

[내용]
상세 내용: 구매시 오류가 발생하였습니다. 오류메시지:[예치금] 초과되었습니다. 초과구매액: 5000
발생 시각: 2023-02-16 17:28:12.054154

고민되는 부분

  • 당첨 결과 조회 시 복권 유형을 로또만 vs 전체 복권
    • 로또만 조회 - 추첨일에 원하는 결과만 얻을 수 있음
    • 전체 조회 - 온라인으로 직접 구매한 다른 복권 결과를 잊게될 수 있음, 특히 자동화를 해놓으면 더 잘 잊게된다고 생각함

결과 조회 기능을 reusable workflow로 제공한다

목표

composite action 조각들을 모아서 결과 조회 기능을 하나의 reusable workflow로 제공한다


TODO

  • reusable workflow 생성
  • issue create api는 더 신뢰도 있는 actions을 가져다 쓰도록 변경
  • private repo에서도 사용해보기
  • 추후 태그 따서 태그로 참조하게 변경해야 함

다른 계정의 private repository에서 테스트 완료

image

image


사용 예시

name: 👀 로또 결과 확인

on:
  workflow_dispatch:
  schedule:
    - cron: '30 2 * * *'


jobs:
  result:
    uses: viiviii/jubilant-train/.github/workflows/result.yml@56082e82b4954f5dd9b2529662fe0d1cee9ea7ad
    secrets:
      id: ${{ secrets.LOTTERY_ACCOUNT_ID }}
      password: ${{ secrets.LOTTERY_ACCOUNT_PASSWORD }}
  
  # 결과를 git issue나 다른 곳에서 쓰고 싶은 경우
  send:
    runs-on: ubuntu-latest
    needs: result

    # 💡 permission은 private repository에서만 필요함
    permissions:
      contents: read
      issues: write

    steps:
      - name: 'Send result to Issue'
        uses: octokit/[email protected]
        with:
          route: POST /repos/${{ github.repository }}/issues
          title: ${{ format('🎊 {0} {1}({2})', needs.result.outputs.name, needs.result.outputs.round, needs.result.outputs.draw-date) }}
          body: |
            |
            ### 요약 
            ```
            총 당첨금: ${{ needs.result.outputs.prize }}
            총 구입매수: ${{ needs.result.outputs.quantity }}
            조회기간: ${{ needs.result.outputs.start-date }} ~ ${{ needs.result.outputs.end-date }}
            ```
            
            ### 상세
            ${{ needs.result.outputs.table }}
          labels: '[👀결과조회]'
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

로또 구매 기능을 reusable workflow로 제공한다

사용 예시

name: 🎁 로또 구매

on:
  workflow_dispatch:
  schedule:
    - cron: '0 1 * * 1-6'

jobs:
  purchase:
    uses: viiviii/jubilant-train/.github/workflows/purchase.yml@46fd432cefaf9733a34a8f52133fb622d48b6ae8
    secrets:
      id: ${{ secrets.LOTTERY_ACCOUNT_ID }}
      password: ${{ secrets.LOTTERY_ACCOUNT_PASSWORD }}
    with:
      amount: 1
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.