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
206 changes: 206 additions & 0 deletions Board.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import os
import sys
from User import User
from Post import Post

SAVE_FILE_PATH = 'save.csv'

class PostNotFoundError(Exception):
pass

def autosave(func):
def decorated(caller, *args, **kwargs):
func(caller, *args, **kwargs)
caller.save()
return decorated

def auto_check_authority(func):
def decorated(caller, *args, **kwargs):
article = func(caller, *args, **kwargs)
caller.check_authorization(article)
return article
return decorated

class Board():
POSTS_PER_PAGE = 15

def __init__(self):
self.current_page = 1
self.posts = list()
try:
self.load()
except FileNotFoundError:
pass
try:
User.load()
except FileNotFoundError:
pass
self.login_actions = [
{
'title' : '로그인하기',
'handler' : self.login
},
{
'title' : '회원가입하기',
'handler' : self.create_user
}
]
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_undeleted():
return index, post
raise PostNotFoundError

def get_undeleted_posts(self, post):
if post.is_undeleted():
self.undeleted_posts.append(post)

def list_posts(self):
self.undeleted_posts = list()
for post in self.posts:
self.get_undeleted_posts(post)

if len(self.undeleted_posts) == 0:
print('게시판에 아직 작성된 글이 없습니다.')
print('한 번 작성해보는 것은 어떨까요?')
return

page_from = (self.current_page - 1) * Board.POSTS_PER_PAGE
page_to = self.current_page * Board.POSTS_PER_PAGE
for post in self.undeleted_posts[page_from : page_to]:
print(post)

@autosave
def create_post(self):
title = input('작성 > ')
self.posts.insert(0, Post(title, self.user.user_id, 'UNDELETED'))

def check_authorization(self, post):
self.post_authorization = self.user.user_id == post.user_id

@auto_check_authority
def get_updated_post(self):
try:
pid = input('몇 번 글을 수정할까요? ')
_, post = self.search_post_by_id(pid)
return post
except (PostNotFoundError, IndexError):
input('잘못된 글 번호를 입력하셨습니다.')
pass

@autosave
def update_post(self):
post = self.get_updated_post()

if not self.post_authorization:
input('{}님은 글 수정 권한이 없습니다.'.format(self.user.user_id))
return

try:
new_title = input('수정 > ')
post.update(new_title)
except (PostNotFoundError, IndexError, ValueError): #indexerror를 만드신 이유가 있을까
input('잘못된 글 번호를 입력하셨습니다.')

@auto_check_authority
def get_deleted_post(self):
try:
pid = input('몇 번 글을 삭제할까요?')
_, post = self.search_post_by_id(pid)
except (PostNotFoundError, IndexError):
input('잘못된 글 번호를 입력하셨습니다.')
return post

@autosave
def delete_post(self):
post = self.get_deleted_post()

if not self.post_authorization:
input('{}님은 글 삭제 권한이 없습니다.'.format(self.user.user_id))
return

try:
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:
return

self.current_page -= 1

def go_next_page(self):
if self.current_page * Board.POSTS_PER_PAGE < len(self.posts):
self.current_page += 1

def print_login_actions(self):
print('-' * 100)
for index, action in enumerate(self.login_actions):
print('{}. {}'.format(index + 1, action.get('title')))
print('-' * 100)

def get_user_login_action(self):
try:
login_action_index = int(input('> '))
self.login_actions[login_action_index - 1]['handler']()
except (IndexError, ValueError):
input('잘못된 행동 번호를 입력하셨습니다.')

def login(self):
self.user = User.login()

def create_user(self):
self.user = User.create_user()
35 changes: 35 additions & 0 deletions Post.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import datetime

class Post():
pid = 1

def __init__(self, title, user_id, deleted_at, pid=None, created_at=None):
self.pid = str(Post.pid) if pid is None else pid
self.title = title
self.user_id = user_id
self.deleted_at = deleted_at
self.created_at = datetime.datetime.now().strftime("%Y-%m-%d %H:%M") if created_at is None else created_at
Post.pid += 1

def __str__(self):
return '{:^8} | {:60.60} | {} | {}'.format(self.pid, self.title, self.user_id, self.created_at)

def update(self, new):
self.title = new

def delete(self):
self.deleted_at = 'DELETE'

def is_undeleted(self):
return self.deleted_at == 'UNDELETED'

def has_pid(self, pid):
return self.pid == pid

@classmethod
def from_csv(cls, csv):
pid, title, user_id, created_at, deleted_at = csv[:-1].split(',')
return cls(title, user_id, deleted_at, pid, created_at)

def to_csv(self):
return '{},{},{},{},{}'.format(self.pid, self.title, self.user_id, self.created_at, self.deleted_at)
94 changes: 94 additions & 0 deletions User.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import hashlib
import os
import sys

def clear_screen():
os.system('cls' if os.name == 'nt' else 'clear')

def get_hashed_password(password):
hashed_password = hashlib.sha256(password.encode()).hexdigest()
return hashed_password

class UserNotFoundError(Exception):
pass

SAVE_FILE_PATH = 'User.csv'

class User:
users = {}
login_success = False

def __init__(self, user_id):
self.user_id = user_id

@classmethod
def is_success(cls, user_id, user_pw):
if cls.users[user_id] == user_pw:
input('로그인에 성공하였습니다.')
return True

@classmethod
def check_existence_of_user_id(cls, user_id):
try:
cls.users[user_id]
User.user_id_existence = True
except (KeyError):
print('아이디가 없습니다. 다시 입력해주세요.')

@classmethod
def get_user_id_and_pw(cls):
User.user_id_existence = False
while not User.user_id_existence:
user_id = input('아이디 입력>')
cls.check_existence_of_user_id(user_id)
user_pw = get_hashed_password(input('비밀번호를 입력하세요>'))
return (user_id, user_pw)

@classmethod
def login(cls):
user_id, user_pw = cls.get_user_id_and_pw()
User.login_success = cls.is_success(user_id, user_pw)
while not User.login_success:
input('비밀번호가 틀렸습니다. 엔터를 누르고 다시 입력해주세요.')
user_pw = get_hashed_password(input('비밀번호를 입력하세요>'))
User.login_success = cls.is_success(user_id, user_pw)
return User(user_id)

@classmethod
def save(cls):
global SAVE_FILE_PATH
f = open(SAVE_FILE_PATH, 'w', encoding='utf-8')
for user_id, user_pw in cls.users.items():
print(cls.to_csv(user_id,user_pw), file = f)
f.close()

@classmethod
def to_csv(cls, user_id, user_pw):
return '{},{}'.format(user_id, user_pw)

@classmethod
def load(cls):
global SAVE_FILE_PATH
f = open(SAVE_FILE_PATH, 'r', encoding = 'utf-8')
users = f.readlines()

for user in users:
user_id, user_pw = cls.from_csv(user)
cls.users[user_id] = user_pw

@classmethod
def create_user(cls):
new_user_id = input('아이디 작성>')
if new_user_id in User.users:
input('이미 존재하는 ID입니다.')
return
new_user_pw = get_hashed_password(input('비밀번호를 입력하세요>'))
cls.users[new_user_id] = new_user_pw
cls.save()
return User(new_user_id)

@classmethod
def from_csv(cls, csv):
user_id, user_pw = csv[:-1].split(',')
return (user_id, user_pw)

33 changes: 33 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import os
import sys
from User import User
from Post import Post
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()
board = Board()
while not User.login_success:
clear_screen()
board.print_login_actions()
board.get_user_login_action()
while True:
clear_screen()
board.list_posts()
board.print_actions()
board.get_user_action()