'''
需求:
# 编写小说阅读程序实现下属功能
# 一:程序运行开始时显示
# 0 账号注册
# 1 充值功能
# 2 阅读小说
# 二: 针对文件db.txt,内容格式为:"用户名:密码:金额",完成下述功能
# 2.1、账号注册
# 2.2、充值功能
# 三:文件story_class.txt存放类别与小说文件路径,如下,读出来后可用eval反解出字典
# {"0":{"0":["倚天屠狗记.txt",3],"1":["沙雕英雄转.txt",10]},"1":{"0":["令人羞耻的爱.txt",6],"1":["二狗的妻子与大草原的故事.txt",5]},}
# 3.1、用户登录成功后显示如下内容,根据用户选择,显示对应品类的小说编号、小说名字、以及小说的价格
"""
0 玄幻武侠
1 都市爱情
2 高效养猪36技
"""
# 3.2、用户输入具体的小说编号,提示是否付费,用户输入y确定后,扣费并显示小说内容,如果余额不足则提示余额不足
# 四:为功能2.2、3.1、3.2编写认证功能装饰器,要求必须登录后才能执行操作
# 五:为功能2.2、3.2编写记录日志的装饰器,日志格式为:"时间 用户名 操作(充值or消费) 金额"
# 附加:
# 可以拓展作者模块,作者可以上传自己的作品
'''
'''
项目目录
小说阅读程序
book_list
二狗的妻子与大草原的故事.txt
令人羞耻的爱.txt
倚天屠狗记.txt
沙雕英雄转.txt
高效养猪36技(01).txt
高效养猪36技(02).txt
高效养猪36技(03).txt
高效养猪36技(04).txt
access.log
auther.py
db.txt
story_class.txt
小说阅读程序.py
'''
import os
def upload(story_dic):
src = input(r'上传的小说路径:').strip()
price = input('小说价格(元):').strip()
if not os.path.exists(src):
return print('上传失败,小说路径错误')
with open(r'story_class.txt.swap', 'wt', encoding='utf-8') as w:
# print(story_dic)
book_name = src.split('\\')[-1]
new_book_list = [book_name, int(price)]
k = len(story_dic['2'])
story_dic['2'][str(k)] = new_book_list
w.write(f'{story_dic}')
print('上传成功')
# upload()
import os
import time
import auther
login_user = None
class_dic = {}
# 判断用户是否存在
def is_user(inp_user):
if not os.path.exists(r'db.txt'):
return False
with open('db.txt','rt', encoding='utf-8') as f:
for is_user in f:
user, *_ = is_user.strip().split(':')
if inp_user == user:
return True
else:
return False
# 登录认证的装饰器
def is_login(func):
def wrapper():
global login_user
if login_user:
func()
else:
res = login()
return func() if res else print('用户名不存在')
return wrapper
def login():
global login_user
while True:
inp_name = input('用户名:').strip()
inp_pwd = input('密码:').strip()
if not is_user(inp_name):
return False
with open(r'db.txt', 'rt', encoding='utf-8') as f:
for line in f:
user, pwd, *_ = line.strip().split(':')
if inp_name == user and inp_pwd == pwd:
login_user = inp_name
print('欢迎,【%s】' % login_user)
return True
else:
print('密码错误')
def register():
while True:
inp_user = input('请输入用户名:').strip()
inp_pwd = input('请输入密码:').strip()
inp_pwd2 = input('请确认密码:').strip()
first_money = 0
if inp_pwd != inp_pwd2:
print('两次密码不一致')
continue
if inp_user and inp_pwd and inp_pwd2:
if is_user(inp_user):
print("用户名已存在")
continue
else:
with open(r'db.txt', 'at', encoding='utf-8') as f:
f.write('{}:{}:{}\n'.format(inp_user, inp_pwd, first_money))
return print("注册成功")
else:
print("输入不能为空")
# 记录消费充值日志的装饰器
def access_log(modle):
def inner(func):
def wrapper(*args, **kwargs):
with open(r'access.log', 'at', encoding='utf-8') as log:
global login_user
if modle == 'recharge':
start_time = time.strftime('%Y-%m-%d %X')
money = func(*args, **kwargs)
if money is not None:
log.write(f'{start_time} {login_user} 充值 {money}元\n')
elif modle == 'story':
start_time = time.strftime('%Y-%m-%d %X')
money = func(*args, **kwargs)
if money == 302:
# print('阅读失败,用户取消支付')
return 302
elif money == 303:
# print("阅读失败,余额不足")
return 303
else:
log.write(f'{start_time} {login_user} 消费 {money}元\n')
return 200
return wrapper
return inner
@is_login
@access_log(modle='recharge')
def recharge():
inp_user = input("请输入用户名:").strip()
inp_money = input("请输入充值金额:").strip()
# 判断用户是否存在
if not is_user(inp_user):
return print("用户名不存在")
# 开始执行充值
with open(r'db.txt', 'rt', encoding='utf-8') as r,\
open(r'db.txt.swap', 'wt', encoding='utf-8') as w:
for line in r:
user, pwd, money = line.strip().split(':')
if inp_user == user and pwd and money:
new_money = int(money) + int(inp_money)
w.write('{}:{}:{}\n'.format(inp_user, pwd, new_money))
else:
w.write('{}:{}:{}\n'.format(user, pwd, money))
os.remove('db.txt')
os.rename('db.txt.swap', 'db.txt')
print('充值成功')
return inp_money
@is_login
def read_story():
func_story = '''
0 玄幻武侠
1 都市爱情
2 高效养猪36技
3 上传小说
'''
# 将图书信息字典设为全局并在局部调用全局
global class_dic
if not os.path.exists('story_class.txt'):
print("暂无小说")
return 404
print(func_story)
with open(r'story_class.txt', 'rt', encoding='utf-8') as f:
# 将文件中字典格式的图书信息字符串转换成图书信息字典赋给全局的class_dic
class_dic = eval(f.read())
inp_num = input('请输入小说类别编号:').strip()
# 作者模块上传小说
if inp_num == '3':
auther.upload(class_dic)
elif inp_num in class_dic:
print('编号 书名 价格'.center(6, ' '))
# 打印编号 书名 价格
for story_dic in class_dic[inp_num]:
print(f'{story_dic} '
f'《{class_dic[inp_num][story_dic][0].replace(".txt", "")}》 '
f' {class_dic[inp_num][story_dic][1]}元'.center(8, ' '))
story_num = input("请输入小说编号:").strip()
if story_num in class_dic[inp_num]:
# 是否阅读
res = is_read(class_dic[inp_num][story_num])
if res == 200:
# inp_num:小说类别编号 story_num:小说编号
open_story(class_dic[inp_num][story_num][0])
return 200
elif res == 303:
print('阅读失败,余额不足')
return 303
elif res == 302:
print('阅读失败,用户取消支付')
return 302
else:
print('小说不存在')
return 404
else:
print('不存在的编号')
return 404
if os.path.exists('story_class.txt.swap'):
os.remove('story_class.txt')
os.rename('story_class.txt.swap', 'story_class.txt')
# 载入小说
def open_story(src):
print("小说加载中。。。\n")
time.sleep(1)
with open(r'book_list\%s' % src, 'rt', encoding='utf-8') as book:
story = book.read()
print(story)
time.sleep(4)
print("小说加载完毕\n")
time.sleep(5)
# 付费阅读操作
@access_log(modle='story')
def is_read(story_info):
global login_user
book_money = int(story_info[1])
inp = input('是否付费?(y/n):').strip()
if inp in ['y', 'Y', 'n', 'N']:
if inp.lower() == 'y':
# 开始付费操作
with open(r'db.txt', 'rt', encoding='utf-8') as r, \
open(r'db.txt.swap', 'wt', encoding='utf-8') as w:
for line in r:
user, pwd, money = line.strip().split(':')
if login_user == user and pwd and money:
money = int(money)
# 余额不足返回303状态码
if book_money > money:
return 303
else:
new_money = money - book_money
w.write(f'{login_user}:{pwd}:{new_money}\n')
else:
w.write(f'{user}:{pwd}:{money}\n')
os.remove('db.txt')
os.rename('db.txt.swap', 'db.txt')
# 返回图书价格
return book_money
else:
# 用户取消支付返回302状态码
return 302
else:
is_read(story_info)
def main():
func_dic = {
'0': ('账号注册', register),
'1': ('充值功能', recharge),
'2': ('阅读小说', read_story)
}
while True:
print('Umi小说阅读程序')
for index in func_dic:
print('{} {}'.format(index, func_dic[index][0]).center(9, ' '))
cmd = input("请输入功能编号:").strip()
if cmd not in func_dic:
print("必须输入指定功能编号.")
else:
func_dic[cmd][1]()
if __name__ == '__main__':
main()