From 6afe38312489397cecfbe5af6db9ce9151d242fb Mon Sep 17 00:00:00 2001 From: YOO TS <37072010+Baram1213@users.noreply.github.com> Date: Mon, 18 Feb 2019 17:45:04 +0900 Subject: [PATCH] Add files via upload --- board.py | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++ login_page.py | 96 ++++++++++++++++++++++++++++++++++++++ main.py | 34 ++++++++++++++ post.py | 50 ++++++++++++++++++++ user.py | 14 ++++++ 5 files changed, 319 insertions(+) create mode 100644 board.py create mode 100644 login_page.py create mode 100644 main.py create mode 100644 post.py create mode 100644 user.py diff --git a/board.py b/board.py new file mode 100644 index 0000000..096fb9b --- /dev/null +++ b/board.py @@ -0,0 +1,125 @@ +from post import Post +from user import User + +SAVE_FILE_PATH = 'save.csv' + +class PostNotFoundError(Exception): + pass + +def autosave(func): + def wrapper(caller, *args, **kwargs): + func(caller, *args, **kwargs) + caller.save() + return wrapper + +class Board(): + POSTS_PER_PAGE = 15 + + def __init__(self): + self.current_page = 1 + self.posts = list() + try: + self.load() + except FileNotFoundError: + pass + self.actions = [ + { + 'title': '작성하기', + 'handler': self.create_post + }, + { + 'title': '수정하기', + 'handler': self.update_post + }, + { + 'title': '삭제하기', + 'handler': self.delete_post + }, + { + 'title': '이전 페이지로', + 'handler': self.go_prev_page + }, + { + 'title': '다음 페이지로', + 'handler': self.go_next_page + } + ] + + def print_actions(self): + print('-' * 100) + for index, action in enumerate(self.actions): + print('{}. {}'.format(index + 1, action.get('title'))) + print('-' * 100) + + def get_user_action(self): + try: + user_action_index = int(input('> ')) + self.actions[user_action_index - 1]['handler']() + except (IndexError, ValueError): + input('잘못된 행동 번호를 입력하셨습니다.') + + def search_post_by_id(self, pid): + for index, post in enumerate(self.posts): + if post.has_pid(pid) and post.is_not_deleted(): + return index, post + raise PostNotFoundError + + def list_posts(self): + if len(self.posts) == 0: + print('게시판에 아직 작성된 글이 없습니다.') + print('한 번 작성해보는 것은 어떨까요?') + return + + page_from = (self.current_page - 1) * Board.POSTS_PER_PAGE + page_to = self.current_page * Board.POSTS_PER_PAGE + posts = [post for post in self.posts if post.is_not_deleted()] + for post in posts[page_from : page_to]: + print(post) + + @autosave + def create_post(self): + title = input('작성 > ') + user_id = User.logged_in + self.posts.insert(0, Post(title, user_id)) + + @autosave + def update_post(self): + try: + pid = int(input('몇 번 글을 수정할까요? ')) + _, post = self.search_post_by_id(pid) + new_title = input('수정 > ') + post.update(new_title) + except (PostNotFoundError, IndexError, ValueError): + input('잘못된 글 번호를 입력하셨습니다.') + + @autosave + def delete_post(self): + try: + pid = int(input('몇 번 글을 지울까요? ')) + _, post = self.search_post_by_id(pid) + post.delete() + except (PostNotFoundError, IndexError, ValueError): + input('잘못된 글 번호를 입력하셨습니다.') + + def load(self): + global SAVE_FILE_PATH + f = open(SAVE_FILE_PATH, 'r', encoding='utf-8') + posts = f.readlines() + for post in posts: + self.posts.append(Post.from_csv(post)) + f.close() + + def save(self): + global SAVE_FILE_PATH + f = open(SAVE_FILE_PATH, 'w', encoding='utf-8') + for post in self.posts: + print(post.to_csv(), file=f) + f.close() + + def go_prev_page(self): + if self.current_page > 1: + self.current_page -= 1 + + def go_next_page(self): + if self.current_page * Board.POSTS_PER_PAGE < len(self.posts): + self.current_page += 1 \ No newline at end of file diff --git a/login_page.py b/login_page.py new file mode 100644 index 0000000..252347a --- /dev/null +++ b/login_page.py @@ -0,0 +1,96 @@ +import hashlib +from user import User + +SAVE_FILE_PATH = 'user.csv' + +class LoginPage(): + def __init__(self): + self.authentication = False + self.user_id = None + self.user_pw = None + self.users = list() + try: + self.load() + except FileNotFoundError: + pass + self.actions = [self.login, self.join] + + def print_actions(self): + print('-' * 100) + print('1. 로그인') + print('2. 회원가입') + print('-' * 100) + + def get_user_action(self): + try: + user_action_index = int(input('> ')) + except: + input('잘못된 입력입니다.') + return + + if user_action_index > 0 and user_action_index <= len(self.actions): + self.actions[user_action_index - 1]() + return + input('잘못된 입력입니다.') + + @staticmethod + def encrypt_in_sha256(pw): + pw = pw.encode() + encrypted_pw = hashlib.sha256(pw).digest() + return encrypted_pw + + def complete_authentication(self): + self.authentication = True + User.logged_in = self.user_id + input(f'로그인 성공 : 환영합니다 {self.user_id}님!') + + def verify_user(self): + for user in self.users: + if user.user_id == self.user_id and user.user_pw == self.user_pw: + return True + + def check_if_input_is_blank(self): + blank = b"\xe3\xb0\xc4B\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99o\xb9$'\xaeA\xe4d\x9b\x93L\xa4\x95\x99\x1bxR\xb8U" + return self.user_id == '' or self.user_pw == blank + + def check_id_duplication(self): + for user in self.users: + if user.user_id == self.user_id: + return False + return True + + def login(self): + self.user_id = input('아이디 : ') + self.user_pw = str(LoginPage.encrypt_in_sha256(input('비밀번호 : '))) + if self.verify_user(): + self.complete_authentication() + return + input('로그인에 실패하였습니다.') + + def join(self): + self.user_id = input('아이디 : ') + self.user_pw = LoginPage.encrypt_in_sha256(input('비밀번호 : ')) + if self.check_if_input_is_blank() is True: + input('공백을 입력할 수 없습니다.') + return + if self.check_id_duplication() is True: + self.users.insert(0, User(self.user_id, self.user_pw)) + self.save() + self.complete_authentication() + return + input('이미 존재하는 아이디입니다.') + + def load(self): + global SAVE_FILE_PATH + f = open(SAVE_FILE_PATH, 'r', encoding='utf-8') + users = f.readlines() + for user in users: + self.users.append(User.from_csv(user)) + f.close() + + def save(self): + global SAVE_FILE_PATH + f = open(SAVE_FILE_PATH, 'w', encoding='utf-8') + for user in self.users: + print(user.to_csv(), file=f) + f.close() \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..419ea8f --- /dev/null +++ b/main.py @@ -0,0 +1,34 @@ +import os +import sys +from login_page import LoginPage +from user import User +from board import Board + +def clear_screen(): + os.system('cls' if os.name == 'nt' else 'clear') + +def print_greeting_message(): + clear_screen() + greeting_message = ''' + 본 프로그램은 광일공방에서 중고거래 사이트를 기웃기웃 거리던 광일이가 + 어느날 삘이 꽂혀 '아! 여기가 돈 나오는 방석이다!' 생각하자마자 아주 + 급하게 만들어낸 불안정한 중고거래 사이트입니다. 물론 아직은 허접한 + 게시판이지만 1000만 사용자를 꿈꾸는 광일이는 커다란 희망의 씨앗을 마음에 + 품고서 오늘도 밤을 지새우며 코드를 작성합니다. + ''' + print(greeting_message) + input('프로그램을 시작하시려면 로그인하세요...') + +if __name__ == "__main__": + print_greeting_message() + login_page = LoginPage() + while login_page.authentication != True: + clear_screen() + login_page.print_actions() + login_page.get_user_action() + board = Board() + while True: + clear_screen() + board.list_posts() + board.print_actions() + board.get_user_action() \ No newline at end of file diff --git a/post.py b/post.py new file mode 100644 index 0000000..6f993cd --- /dev/null +++ b/post.py @@ -0,0 +1,50 @@ +import datetime +from user import User + +def check_athorization(func_name): + def real_decorator(func): + def wrapper(caller, *args): + if caller.user_id == User.logged_in: + func(caller, *args) + return + input(f'{User.logged_in}님께는 해당 글 {func_name} 권한이 없습니다!') + return wrapper + return real_decorator + +class Post(): + pid = 1 + + def __init__(self, title, user_id, pid=None, created_at=None, deleted=False): + self.pid = Post.pid if pid is None else pid + self.title = title + self.user_id = user_id + self.created_at = datetime.datetime.now().strftime("%Y-%m-%d %H:%M") if created_at is None else created_at + self.deleted = deleted + Post.pid += 1 + + def __str__(self): + return '{:^8} | {:60.60} | {:^10.10} | {}'.format(self.pid, self.title, self.user_id, self.created_at) + + @check_athorization('수정') + def update(self, new): + self.title = new + + def has_pid(self, pid): + return self.pid == pid + + @check_athorization('삭제') + def delete(self): + self.deleted = True + + def is_not_deleted(self): + return self.deleted == False + + @classmethod + def from_csv(cls, csv): + pid, title, user_id, created_at, deleted = csv[:-1].split(',') + pid = int(pid) + deleted = False if deleted == 'False' else True + return cls(title, user_id, pid, created_at, deleted) + + def to_csv(self): + return '{},{},{},{},{}'.format(self.pid, self.title, self.user_id, self.created_at, self.deleted) \ No newline at end of file diff --git a/user.py b/user.py new file mode 100644 index 0000000..b9aaaca --- /dev/null +++ b/user.py @@ -0,0 +1,14 @@ +class User(): + logged_in = None + + def __init__(self, user_id=None, user_pw=None): + self.user_id = user_id + self.user_pw = user_pw + + @classmethod + def from_csv(cls, csv): + user_id, user_pw = csv[:-1].split(',') + return cls(user_id, user_pw) + + def to_csv(self): + return '{},{}'.format(self.user_id, self.user_pw) \ No newline at end of file