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
131 changes: 131 additions & 0 deletions BOARD.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import math
from POST import Post
from USER import User, UserManager
from SAVE import autosave, SAVE_PATH_POST

class PostNotFoundError(Exception):
pass

class Board:
POSTS_PER_PAGE = 15

def __init__(self):
self.posts = list()
self.no_of_pages = 1
self.current_page_no = 1
self.actions = [
{
"title" : "작성하기",
"handler" : self.write_post
},
{
"title" : "수정하기",
"handler" : self.update_post
},
{
"title" : "삭제하기",
"handler" : self.delete_post
},
{
"title" : "저장하기",
"handler" : self.save
},
{
"title" : "이전페이지",
"handler" : self.move_previous_page
},
{
"title" : "다음페이지",
"handler" : self.move_next_page
}]
try:
self.load()
except:
pass

def save(self):
global SAVE_PATH_POST
f = open(SAVE_PATH_POST, 'w+')
for post in self.posts:
print(post.to_csv(), file = f)
f.close()

def load(self):
global SAVE_PATH_POST
f = open(SAVE_PATH_POST, 'r')
posts = f.readlines()
for post in posts:
self.posts.append(Post.from_csv(post))
f.close()

def show_posts(self):
if self.posts == []:
print('게시판에 아직 작성된 글이 없습니다.')
print('한번 작성해보는 것은 어떨까요?')
print('-' * 100)
return

self.posts_shown_list = list(filter(lambda x: x.post_shown_status == True, self.posts))
# or self.posts_shown_list = [post for post in self.posts if post.post_shown_status ==True]
self.no_of_pages = math.ceil( len(self.posts_shown_list) / Board.POSTS_PER_PAGE )

page = [post for index, post in enumerate(self.posts_shown_list) if Board.POSTS_PER_PAGE * (self.current_page_no - 1) <= index < Board.POSTS_PER_PAGE * self.current_page_no]
for post in page:
print(post)
print('-' * 100)

def search_post_by_post_no(self, post_no):
for post in self.posts:
if post.has_post_no(post_no):
return post
raise PostNotFoundError

@autosave
def write_post(self):
post_title = input('작성 >')
self.posts.insert(0, Post(post_title, UserManager.LOGINNED_USER.user_id))
self.current_page_no = 1

@autosave
def update_post(self):
try:
post_no = int(input('몇 번 글을 수정할까요?'))
post = self.search_post_by_post_no(post_no)
post.update_title()
except (PostNotFoundError, ValueError, IndexError):
print("잘못된 글 번호를 입력하셨습니다.")

@autosave
def delete_post(self):
try:
post_no = int(input('몇 번 글을 삭제할까요?'))
post = self.search_post_by_post_no(post_no)
post.change_shown_status()
except (PostNotFoundError, ValueError, IndexError):
print("잘못된 글 번호를 입력하셨습니다.")

def move_previous_page(self):
self.current_page_no -= 1
if self.current_page_no < 1:
self.current_page_no = 1
print("첫 페이지입니다.")

def move_next_page(self):
self.current_page_no += 1
if self.current_page_no > self.no_of_pages:
self.current_page_no = self.no_of_pages
print("마지막 페이지입니다.")

def show_actions(self):
for index, action in enumerate(self.actions):
print("{}. {}".format(index+1, action["title"]))
print('-' * 100)

def execute_action(self):
try:
action_no = int(input('>'))
self.actions[action_no - 1]["handler"]()
except (IndexError, ValueError):
print("잘못된 입력입니다.")

input('엔터를 누르세요.')
54 changes: 54 additions & 0 deletions POST.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import datetime
from USER import User, UserManager

class NotAuthorizedError(Exception):
pass

def check_authorization(action_name):
def wrapper(func):
def inner(caller, *args, **kwargs):
try:
if not caller.is_same_writer():
raise NotAuthorizedError
func(caller, *args, **kwargs)
except NotAuthorizedError:
print("{}님께 {} 권한이 없습니다.".format(UserManager.LOGINNED_USER.user_id, action_name))
return inner
return wrapper

class Post:
COUNT = 0

def __init__(self, post_title, post_writer, post_no = None, post_time=None, post_shown_status=None):
Post.COUNT += 1
self.post_no = Post.COUNT if post_no is None else post_no
self.post_title = post_title
self.post_writer = post_writer
self.post_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M') if post_time is None else post_time
self.post_shown_status = True if post_shown_status is None else post_shown_status

def __str__(self):
return f"{self.post_no:^8} | {self.post_title:60.60} | {self.post_writer:^10.10} | {self.post_time}"

@check_authorization("수정")
def update_title(self):
updated_title = input('수정>')
self.post_title = updated_title

@check_authorization("삭제")
def change_shown_status(self):
self.post_shown_status = False

def has_post_no(self, post_no):
return self.post_no == post_no and self.post_shown_status == True

def is_same_writer(self):
return self.post_writer == UserManager.LOGINNED_USER.user_id

@classmethod
def from_csv(cls, csv):
post_no, post_title, post_writer, post_time, post_shown_status = csv.strip('\n').split(',')
return cls(post_title, post_writer, post_no = int(post_no), post_time = post_time, post_shown_status = post_shown_status == "True")

def to_csv(self):
return f"{self.post_no},{self.post_title},{self.post_writer},{self.post_time},{self.post_shown_status}"
8 changes: 8 additions & 0 deletions SAVE.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
SAVE_PATH_POST = "post.csv"
SAVE_PATH_USER = "user_info.csv"

def autosave(func):
def wrapper(caller, *args, **kwargs):
func(caller)
caller.save()
return wrapper
127 changes: 127 additions & 0 deletions USER.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import hashlib
from SAVE import SAVE_PATH_USER, autosave

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

class ExistingIdError(Exception):
pass

class NotExistingIdError(Exception):
pass

class InvalidPassword(Exception):
pass

class UserManager:
LOGINNED_USER = None

def __init__(self):
self.users = list()
self.action_list = [
{
"title" : "로그인",
"handler" : self.user_login
},
{
"title" : "회원가입",
"handler" : self.user_join
}
]
try:
self.load()
except FileNotFoundError:
pass

def load(self):
global SAVE_PATH_USER
f = open(SAVE_PATH_USER, 'r')
users = f.readlines()
for user in users:
self.users.append(User.from_csv(user))
f.close()

def save(self):
global SAVE_PATH_USER
f = open(SAVE_PATH_USER, 'w')
for user in self.users:
print(user.to_csv(), file = f)
f.close()

def search_user_by_id_for_login(self, user_id):
for user in self.users:
if user.has_id(user_id):
return user
raise NotExistingIdError

def search_user_by_id_for_join(self, user_id):
for user in self.users:
if user.has_id(user_id):
raise ExistingIdError

def user_login(self):
try:
user_id = input("ID를 입력하세요.")
user = self.search_user_by_id_for_login(user_id)

hashed_password = get_hashed_password(input("password를 입력하세요."))
if not user.check_password(hashed_password):
raise InvalidPassword
if user.check_password(hashed_password):
UserManager.LOGINNED_USER = user
print("로그인 성공 : 환영합니다 {}님".format(UserManager.LOGINNED_USER.user_id))
except NotExistingIdError:
print("존재하지 않는 ID입니다.")
except InvalidPassword:
print("비밀번호가 일치하지 않습니다.")

@autosave
def user_join(self):
try:
user_id = input("ID를 입력하세요.")
self.search_user_by_id_for_join(user_id)

hashed_password = get_hashed_password(input("password를 입력하세요."))
user = User(user_id, hashed_password)
self.users.append(user)

UserManager.LOGINNED_USER = user
print("로그인 성공 : 환영합니다 {}님".format(user.user_id))
except ExistingIdError:
print("이미 존재하는 ID입니다.")

def print_actions(self):
print('-' * 100)
for index, action in enumerate(self.action_list):
print("{}. {}".format(index + 1, action["title"]) )
print('-' * 100)

def execute_action(self):
try:
action_no = int(input("번호를 입력하세요."))
self.action_list[action_no - 1]["handler"]()
except (IndexError, ValueError):
print("잘못된 입력입니다.")

input("엔터를 입력하세요.")

class User:

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

@classmethod
def from_csv(cls, csv):
user_id, user_password = csv.strip('\n').split(',')
return cls(user_id, user_password)

def to_csv(self):
return f"{self.user_id},{self.user_password}"

def has_id(self, user_id):
return self.user_id == user_id

def check_password(self, hashed_password):
return self.user_password == hashed_password
32 changes: 32 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import os
from BOARD import Board
from POST import Post
from USER import UserManager, User

def intro():
greeting = '''
본 프로그램은 광일공방에서 중고거래 사이트를 기웃기웃 거리던 광일이가
어느날 삘이 꽂혀 '아! 여기가 돈 나오는 방석이다!' 생각하자마자
아주 급하게 만들어낸 불안정한 중고거래 사이트입니다. 물론 아직은
허접한 게시판이지만 1000만 사용자를 꿈꾸는 광일이는 커다란 희망의 씨앗을
마음에 품고서 오늘도 밤을 지새우며 코드를 작성합니다.

프로그램을 시작하려면 로그인하세요...'''
print(greeting, end = '')
input()
clear_screen()

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

if __name__ == "__main__":
user_manager = UserManager()
while UserManager.LOGINNED_USER == None:
user_manager.print_actions()
user_manager.execute_action()
board = Board()
while True :
board.show_posts()
board.show_actions()
board.execute_action()
clear_screen()