Skip to content
This repository was archived by the owner on Jan 4, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions board.py
Original file line number Diff line number Diff line change
@@ -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
96 changes: 96 additions & 0 deletions login_page.py
Original file line number Diff line number Diff line change
@@ -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()
34 changes: 34 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -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()
50 changes: 50 additions & 0 deletions post.py
Original file line number Diff line number Diff line change
@@ -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)
14 changes: 14 additions & 0 deletions user.py
Original file line number Diff line number Diff line change
@@ -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)