需 求:
********管理员界面********
1 注册
2 登录
3 上传视频
4 删除视频
5 发布公告
********普通用户界面********
1 注册
2 登录
3 冲会员
4 查看视频
5 下载免费视频
6 下载收费视频
7 查看下载记录
8 查看公告
q.退出
软件开发目录:
服务端Server
1 # _*_ coding: gbk _*_ 2 # @Author: Wonder 3 import os 4 BASE_PATH = os.path.dirname(os.path.dirname(__file__)) 5 MOVIE_DIR_PATH = os.path.join(BASE_PATH,'movie') 6 7 IP = '127.0.0.1' 8 PORT = 9527
# _*_ coding: gbk _*_ # @Author: Wonder from orm_control.orm import Models, StringField, IntegerField import datetime ''' 每个字段的四个属性name, field_type, is_primary, default 其中field_type、is_primary、default都有默认值 ''' ''' # 用户表类: id、用户名、密码、用户类型、是否为VIP、注册时间 # 电影表类: id、电影名字、电影大小、电影md5值、电影是否免费、电影是否删除、上传时间、上传用户的id # 公告表类: id、公告标题, 公告内容、发布时间、发布用户id # 下载记录表: id、下载电影的id、下载用户的id、下载时间 ''' class User(Models): ''' # 用户表类: id、用户名、密码、用户类型、是否为VIP、注册时间 ''' u_id = IntegerField(name='u_id', is_primary=True) username = StringField(name='username') password = StringField(name='password') user_type = IntegerField(name='user_type',) # 此处 0为普通用户,1 为管理员,默认值为 is_vip = IntegerField(name='is_vip') # 此处 0 为普通用户,1 为VIP reg_time = StringField(name='reg_time') # 每个字段的默认值,可以在这些个性化的类中进行设置 class Movie(Models): ''' # 电影表类: id、电影名字、电影大小、电影md5值、电影是否免费、电影是否删除、上传时间、上传用户的id ''' m_id = IntegerField(name='m_id', is_primary=True) name = StringField(name='name') size = IntegerField(name='size') md5 = StringField(name='md5') is_free = IntegerField(name='is_free') #默认0是免费,1 是收费 is_del = IntegerField(name='is_del') up_time = StringField(name='movie_name') u_id = IntegerField(name='movie_name') class Notice(Models): ''' id、公告标题, 公告内容、发布时间、发布用户id ''' n_id = IntegerField(name='n_id', is_primary=True) title = StringField(name='title') content = StringField(name='content') release_time = StringField(name='release_time') u_id = IntegerField(name='u_id') class Record(Models): ''' # 下载记录表: id、下载电影的id、下载用户的id、下载时间 ''' r_id = IntegerField(name='r_id', is_primary=True) m_id = IntegerField(name='m_id') u_id = IntegerField(name='u_id') down_time = StringField(name='down_time') if __name__ == '__main__': import time # user_obj = User( # username='张五', # id是不用传值的,因为在数据库中实现了自增 # password ='1234', # user_type=1, # is_vip=0, # reg_time=time.strftime('%Y-%m-%d %X') # ) # user_obj.insert_data() # res = User.select_data() # [ 字典、] # print(res) user_obj = User.select_data(u_id=1)[0] # 这里注意,是个字典套对象,要注意取值 user_obj.username = '张九' user_obj.update_data() res = User.select_data() # [ 字典(对象)、] 这里的对象就是字典,一个特殊的对象,类dict的对象。 print(res)
# _*_ coding: gbk _*_ # @Author: Wonder import os import uuid from conf import settings from lib import common import time from db.models import Notice, Movie @common.login_auth def check_movie_interface(dic, conn, addr): md5 = dic.get('movie_md5') movie_list = Movie.select_data(md5=md5) if movie_list: back_dic = { 'flag': False, 'msg': '电影已存在' } else: back_dic = { 'flag': True, } common.send_data(back_dic, conn) @common.login_auth def upload_movie_interface(dic, conn, addr): movie_size = dic.get('movie_size') movie_name = str(uuid.uuid4()).replace('-', '_') + dic.get('movie_name') # 为了保证名字不同的电影重名时,能保存 movie_path = os.path.join(settings.MOVIE_DIR_PATH, movie_name) temp_size = 0 with open(movie_path, 'wb') as f: while temp_size < movie_size: data = conn.recv(1024) f.write(data) temp_size += len(data) back_dic = { 'msg': '传完了' } mv_obj = Movie( name=movie_name, size=movie_size, md5=dic.get('movie_md5'), is_free=dic.get('is_free'), up_time=time.strftime('%Y-%m-%d %X'), u_id=dic.get('u_id'), ) print(1) mv_obj.insert_data() print(2) common.send_data(back_dic, conn) @common.login_auth def del_mv_interface(dic, conn, addr): movie_name = dic.get('mv_name') mv_obj = Movie.select_data(name=movie_name)[0] mv_obj.is_del = 1 mv_obj.update_data() back_dic = { 'msg': f'{mv_obj.name}已删除' } print('看一眼') common.send_data(back_dic, conn) @common.login_auth def relaese_notice_interface(dic, conn, addr): notice_obj = Notice( title=dic.get('title'), content=dic.get('content'), release_time=time.strftime('%Y-%m-%d %X'), u_id=dic.get('u_id') ) print(notice_obj) notice_obj.insert_data() back_dic = {'msg': '公告发布成功'} common.send_data(back_dic, conn)
# _*_ coding: gbk _*_ # @Author: Wonder from db.models import User from user_data import session from lib import common import time from db.models import User, Movie # from tcp_server.server import mutex from threading import Lock # mutex = Lock() # 注册接口 def register_interface(dic, conn, addr): username = dic.get('username') user_type = dic.get('user_type') user_list = User.select_data(username=username) if user_list: send_dic = { 'flag': False, 'msg': '用户已存在' } else: user_obj = User( username=username, user_type=user_type, password=common.get_md5(dic.get('password')), reg_time=time.strftime('%Y-%m-%d %X'), ) user_obj.insert_data() send_dic = { 'flag': True, 'msg': '注册成功' } common.send_data(send_dic, conn) # 登录接口 核对登录密码,更新session文件 def login_interface(dic, conn, addr): username = dic.get('username') user_list = User.select_data(username=username) if not user_list: dic = { 'flag': False, 'msg': '用户不存在' } common.send_data(dic, conn) else: input_pwd = common.get_md5(dic.get('password')) input_type = dic.get('user_type') record_pwd = user_list[0].get('password') record_type = user_list[0].get('user_type') if not input_pwd == record_pwd: dic = { 'flag': False, 'msg': '用户名或密码不正确' } common.send_data(dic, conn) elif not input_type == record_type: print('传来的',input_type) print('系统的',record_type) dic = { 'flag': False, 'msg': '非法用户' } common.send_data(dic, conn) else: u_id = user_list[0].get('u_id') is_vip = user_list[0].get('is_vip') new_session = common.get_session() # mutex.locked() session.user_info[addr] = [new_session, u_id] # mutex.release() dic = { 'flag': True, 'msg': '登录成功', 'session': new_session, 'u_id': u_id, 'is_vip': is_vip } # print('服务端的session',dic) common.send_data(dic, conn) # 查看没有被删除的所有电影 @common.login_auth def check_nodel_movie_interface(dic, conn, addr): # 查出来可以删除的电影 is_del=0 mv_obj_list = Movie.select_data() if not mv_obj_list: dic = { 'flag': False, 'msg': '没有电影' } else: mv_name_list = [i for i in mv_obj_list if i.is_del == 0] # 找出所有没有删除的 free_mv_list = [i.name for i in mv_name_list if i.is_free == 0] # 找出没删除的 免费 的 名字 # print('免费的电影', free_mv_list) pay_mv_list = [i.name for i in mv_name_list if i.is_free == 1] # 找出没删除 付费的 的名字 # print('收费的电影', pay_mv_list) if dic.get('select_type') == 'all': mv_list = free_mv_list mv_list.extend(pay_mv_list) elif dic.get('select_type') == 'free': mv_list = free_mv_list else: mv_list = pay_mv_list if not mv_list: dic = { 'flag': False, 'msg': '没有电影' } else: dic = { 'flag': True, 'mv_list': mv_list } common.send_data(dic, conn)
# _*_ coding: gbk _*_ # @Author: Wonder import os import time from db.models import User, Record, Movie, Notice from conf.settings import MOVIE_DIR_PATH from lib import common # 充值会员接口 @common.login_auth def paymember_interface(dic, conn, addr): print('开始充钱啦') user_obj = User.select_data( u_id=dic.get('u_id') )[0] print(user_obj) user_obj.is_vip = 1 user_obj.update_data() back_dic = { 'msg': '充值成功' } common.send_data(back_dic, conn) # 下载电影接口 @common.login_auth def download_mv_interface(dic, conn, addr): mv_name = dic.get('mv_name') # 打开服务器端供下载的文件夹 file_path = os.path.join(MOVIE_DIR_PATH, mv_name) mv_size = os.path.getsize(file_path) back_dic = { 'mv_size': mv_size } # 下载完了之后,还要将下载记录插入到下载表中 mv_obj = Movie.select_data(name=mv_name) # 在此处通过名字取值,会增加数据库负担 m_id = mv_obj[0].m_id #单个一定要指定0,否则不执行 rec_obj = Record( m_id=m_id, u_id=dic.get('u_id'), # 装饰器给加进去的 down_time=time.strftime('%Y-%m-%d %X') ) rec_obj.insert_data() common.send_data(back_dic, conn, file_path) # 将报头和内容进行整合 #查看下载记录 @common.login_auth def check_record_interface(dic, conn, addr): u_id = dic.get('u_id') record_obj = Record.select_data(u_id=u_id) if not record_obj: back_dic = { 'flag': False, 'msg': '没有下载记录' } else: movie_id_list = [i.m_id for i in record_obj] # 将电影的id取出来 mv_obj = Movie.select_data() movie_list = [i.name for i in mv_obj if i.m_id in movie_id_list] # 取出名字 back_dic = { 'flag': True, 'mv_list': movie_list } common.send_data(back_dic, conn) # 查看下载记录 @common.login_auth def check_notice_interface(dic, conn, addr): notice_obj = Notice.select_data() if not notice_obj: back_dic = { 'flag': False, 'msg': '没有公告' } else: notice_list = [f'标题{i.title},内容{i.content}' for i in notice_obj] back_dic = { 'flag': True, 'notice_list': notice_list } common.send_data(back_dic, conn)
# _*_ coding: gbk _*_ # @Author: Wonder import json import struct from hashlib import md5 import uuid from user_data import session # from tcp_server.server import mutex from threading import Lock # mutex = Lock() # 发数据 def send_data(dic, conn, path=None): send_dic = json.dumps(dic).encode('utf-8') send_head = struct.pack('i', len(send_dic)) conn.send(send_head) conn.send(send_dic) if path: with open(path, 'rb') as f: for line in f: conn.send(line) # md5进行加密 def get_md5(pwd): md5_obj = md5() md5_obj.update(pwd.encode('utf-8')) sal = 'youku_sys' md5_obj.update(sal.encode('utf-8')) return md5_obj.hexdigest() # 获取一个session随机字符串 def get_session(): rand_str = str(uuid.uuid4()) return get_md5(rand_str) # 登录 验证装饰器 def login_auth(func): # 将用户id添加到字典中 def inner(*args, **kwargs): # *args (dic,conn ,addr) print('进入装饰器啦------------') recv_dic = args[0] conn = args[1] client_session = recv_dic.get('cookies') addr = args[2] # print('打印一下文件中是否有内容',session.user_info) # mutex.locked() server_session = session.user_info.get(addr) # mutex.release() if server_session: if client_session == server_session[0]: recv_dic['u_id'] = server_session[1] res = func(*args, **kwargs) return res else: dic = { 'flag': False, 'msg': '重新登陆' } send_data(dic, conn) else: dic = { 'flag': False, 'msg': '******请先登陆******' } send_data(dic, conn) return inner if __name__ == '__main__': msg = get_md5('www') print(msg)
# _*_ coding: gbk _*_ # @Author: Wonder from DBUtils.PooledDB import PooledDB import pymysql Pool = PooledDB( # creator, # mincached=0, # maxcached=0, # maxshared=0, # maxconnections=0, # blocking=False, # maxusage=None, # setsession=None, # reset=True, # failures=None, # ping=1, creator=pymysql, # 使用链接数据库的模块 maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数 mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建 maxcached=5, # 链接池中最多闲置的链接,0和None不限制 maxshared=3, # 链接池中最多共享的链接数量,0和None表示全部共享。 # PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。 blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错 maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制 setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always host='127.0.0.1', port=3306, user='root', password='1234,5678a', database='orm_mysql_demo', charset='utf8', autocommit=True )
# _*_ coding: gbk _*_ # @Author: Wonder import pymysql from orm_control.mysql_pool import Pool class MySql(): # 数据库连接用单例模式 def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance', ): setattr(cls, '_instance', object.__new__(cls)) return cls._instance def __init__(self): self.mysql_client = Pool.connection() self.cursor = self.mysql_client.cursor( pymysql.cursors.DictCursor) def select(self, sql, args=None): self.cursor.execute(sql, args) res = self.cursor.fetchall() return res def execute(self, sql, args): try: self.cursor.execute(sql, args) except Exception as e: print(e) def close(self): self.cursor.close() self.mysql_client.close() # # if __name__ == '__main__': # obj1 =MySql() # obj2 =MySql() # obj3 =MySql() # print(id(obj1)) # print(id(obj2)) # print(id(obj3))
# _*_ coding: gbk _*_ # @Author: Wonder from orm_control.mysql_pro import MySql class Field: def __init__(self, name, field_type, is_primary, default): self.name = name self.field_type = field_type self.is_primary = is_primary self.default = default class StringField(Field): def __init__(self, name, field_type='varchar(255)', is_primary=False, default=None): super().__init__(name, field_type, is_primary, default) class IntegerField(Field): def __init__(self, name, field_type='int', is_primary=False, default=0): super().__init__(name, field_type, is_primary, default) class OrmCtrl(type): def __new__(cls, class_name, class_bases, class_dict): if class_name == 'Models': return type.__new__(cls, class_name, class_bases, class_dict) # 此时筛选出来的就是继承Field产生的类,需要控制他们类的创建过程 primary_key = None # table_name = getattr(cls, 'table_name', class_name) # 取User类中的table_name属性(如果传就用table_name) table_name = class_dict.get('table_name', class_name) # 看有没有创建并传一个叫table_name的字段信息 mappings = {} # 字典里存放User类的字段 for k, v in class_dict.items(): if isinstance(v, Field): # 筛选出Field的创建的对象,即User等之类的表 mappings[k] = v # 将合格的k、v转义到mappings中 if v.is_primary: # 表示这个字段是主键 V是一个由Field生成的对象 if primary_key: raise TypeError('只能有一个主键') primary_key = v.name if not primary_key: raise TypeError('必须要有主键') for k in mappings: class_dict.pop(k) class_dict['table_name'] = table_name class_dict['primary_key'] = primary_key class_dict['mappings'] = mappings return type.__new__(cls, class_name, class_bases, class_dict) # 都要交给元类type进行类的创建 class Models(dict, metaclass=OrmCtrl): ''' 控制实际表类对象的生成,干涉其取值方式。因为继承了字典,所以通过该类生成的对象都是字典 ''' def __getattr__(self, item): return self.get(item) def __setattr__(self, key, value): self[key] = value @classmethod def select_data(cls, **kwargs): mysql_obj = MySql() if not kwargs: # 说明想查cls这张表里面的所有值 sql = f'select * from {cls.table_name}' res = mysql_obj.select(sql) else: # kwargs-->** kwargs a=b --> {a:b} # 开始取字典中的key dict1.keys()是一个对象 key = list(kwargs.keys())[0] value = kwargs.get(key) sql = f'select * from {cls.table_name} where {key} = %s' res = mysql_obj.select(sql, value) # 此时获取的两种res 都是列表套字典 return [cls(**i) for i in res] # 此时将列表中的字典,转化成了对象,就有了相关的属性,比如name,field_type def insert_data(self): # obj = User(name = 'ccc') # 此功能仅实现一次插入一条记录 sql_obj = MySql() list_k = [] # 添加传来的key list_value = [] # 添加传来的值 list_tag = [] for k, v in self.mappings.items(): # kv只能在items()中取值 list_k.append(k) # mappings的k都是字符串,因为是user的属性名 list_tag.append('%s') list_value.append(self.get(k, v.default)) # insert into t1 (id,name) values(1,ww),(2,xx) sql = f'insert into {self.table_name} (%s) values (%s)' %( ','.join(list_k), ','.join(list_tag) ) sql_obj.execute(sql, list_value) def update_data(self): # 更新的时候,敏感数据是更新的值,要单独传 sql_obj = MySql() update_list = [] # 将要准备更新的数据,以字符串的形式 存在这里面 update_value = [] pk = None pk_value = None for k, v in self.mappings.items(): if not v.is_primary: update_list.append(f'{k}=%s') update_value.append(self.get(k, v.default)) pk = self.primary_key pk_value = self.get(pk) # 主键一定是有的 sql = f'update {self.table_name} set %s where %s = %s ' %( ','.join(update_list), pk, pk_value ) print('更新的语句', sql) sql_obj.execute(sql, update_value)
# _*_ coding: gbk _*_ # @Author: Wonder import socket import struct import json from user_data.session import user_info from concurrent.futures import ThreadPoolExecutor from interface import common_interface from interface import admin_interface from interface import user_interface from threading import Lock # mutex = Lock() func_dict = { 'register': common_interface.register_interface, 'login': common_interface.login_interface, 'check_movie': admin_interface.check_movie_interface, 'upload_movie': admin_interface.upload_movie_interface, 'check_nodel_movie': common_interface.check_nodel_movie_interface, # 未删除的所有电影 'del_mv': admin_interface.del_mv_interface, 'release_notice': admin_interface.relaese_notice_interface, 'pay_member': user_interface.paymember_interface, 'download_mv': user_interface.download_mv_interface, 'check_record': user_interface.check_record_interface, 'check_notice': user_interface.check_notice_interface } pool = ThreadPoolExecutor(5) def connect(ip, port): server = socket.socket() server.bind((ip, port)) server.listen(5) print('server start.....') while True: conn, addr = server.accept() pool.submit(task, conn, addr) # 并发 def task(conn, addr): while True: try: recv_data = conn.recv(4) dic_size = struct.unpack('i', recv_data)[0] json_dic = conn.recv(dic_size).decode('utf-8') recv_dic = json.loads(json_dic) func_type = recv_dic.get('func_type') if func_type in func_dict: # print(recv_dic,'收到的字典') func_dict.get(func_type)(recv_dic, conn, addr) except Exception as e: # print(e) # mutex.acquire() user_info.pop(str(addr)) # {str(addr) : [session, u_id ] } # mutex.release() break conn.close()
# _*_ coding: gbk _*_ # @Author: Wonder user_info = {} # {(ip:port) : [session, u_id}
# _*_ coding: gbk _*_ # @Author: Wonder import sys from conf import settings from tcp_server import server sys.path.append(settings.BASE_PATH) if __name__ == '__main__': server.connect(settings.IP, settings.PORT)
客户端Client
# _*_ coding: gbk _*_ # @Author: Wonder import os BASE_PATH = os.path.dirname(os.path.dirname(__file__)) DOWNLOAD_PATH = os.path.join(BASE_PATH, 'download_movie') UPLOAD_PATH = os.path.join(BASE_PATH, 'upload_movie') IP = '127.0.0.1' PORT = 9527
# _*_ coding: gbk _*_ # @Author: Wonder from lib import common import os import time from conf.settings import UPLOAD_PATH current_user = { 'cookies': None } # 注册 def register(client): while True: username = input('>>>请输入用户名').strip() password = input('>>>请输入密码').strip() re_password = input('>>>请再次输入密码').strip() if not password == re_password: print('密码不一致') continue dic = { 'func_type': 'register', 'username': username, 'password': password, 'user_type': 1 } back_dic = common.send_and_back(dic, client) if back_dic.get('flag'): print(back_dic.get('msg')) break else: print(back_dic.get('msg')) choice = input('>>>是否继续注册,q退出').strip() if choice == 'q': break else: continue # 登录 def login(client): while True: username = input('>>>请输入用户名').strip() password = input('>>>请输入密码').strip() send_dic = { 'func_type': 'login', 'username': username, 'password': password, 'user_type': 1 } back_dic = common.send_and_back(send_dic, client) print(back_dic, '客户端的') if back_dic.get('flag'): cookies = back_dic.get('session') current_user['cookies'] = cookies msg = back_dic.get('msg') print(msg) break else: print(back_dic.get('msg')) choice = input('>>>是否继续登录,q退出').strip() if choice == 'q': break else: continue # 上传电影 def upload_mv(client): # 上传电影 # 电影目录 while True: movie_list = os.listdir(UPLOAD_PATH) if not movie_list: print('无可上传电影') break else: flag, msg = common.show_and_choice(movie_list) if not flag: print(msg) continue else: movie_path = os.path.join(UPLOAD_PATH, msg) movie_size = os.path.getsize(movie_path) # 先判断电影在不在(先取所有的内容,后面优化定点取值) movie_md5 = common.get_movie_md5(movie_path) dic1 = { 'func_type': 'check_movie', 'movie_md5': movie_md5, 'cookies': current_user.get('cookies') } print('组织的字典', dic1) back_dic = common.send_and_back(dic1, client) print('收到的字典', back_dic) if not back_dic.get('flag'): print(back_dic.get('msg')) break else: # 开始上传啦 choice = input('>>>选择是否收费,y收费,任意键免费').strip() if choice == 'y': is_free = 1 else: is_free = 0 dic = { 'func_type': 'upload_movie', 'movie_name': msg, 'movie_size': movie_size, 'movie_md5': movie_md5, 'is_free': is_free, 'cookies': current_user.get('cookies') } back_dic = common.send_and_back(dic, client, path=movie_path) print(back_dic.get('msg')) break # 删除电影 def delete_mv(client): # 获取电影列表 while True: dic = { 'func_type': 'check_nodel_movie', 'cookies': current_user.get('cookies'), 'select_type': 'all' } back_dic = common.send_and_back(dic, client) print('返回的报头', back_dic) if not back_dic.get('flag'): print(back_dic.get('msg')) break else: mv_list = back_dic.get('mv_list') print('可删除的列表', mv_list) flag, msg = common.show_and_choice(mv_list) if not flag: print(msg) break else: del_mv_name = msg dic2 = { 'func_type': 'del_mv', 'cookies': current_user.get('cookies'), 'mv_name': del_mv_name } print(dic2) back_dic = common.send_and_back(dic2, client) print(back_dic.get('msg')) break # 发布公告 def announce(client): title = input('>>>请输入公告标题').strip() content = input('>>请输入公告内容').strip() dic = { 'func_type': 'release_notice', 'title': title, 'content': content, 'cookies': current_user.get('cookies') } back_dict = common.send_and_back(dic, client) print(back_dict.get('msg')) def run(client): func_dict = { '1': register, '2': login, '3': upload_mv, '4': delete_mv, '5': announce, } while True: print(''' ********管理员界面******** 1 注册 2 登录 3 上传视频 4 删除视频 5 发布公告 任意键退出 ''') choice = input('>>>请选择功能').strip() if choice in func_dict: func_dict.get(choice)(client) else: print('告辞') break
# _*_ coding: gbk _*_ # @Author: Wonder from core import admin_view, user_view from tcp_client.client import connect def run(): func_dict = { '1': admin_view, '2': user_view } while True: client = connect() print(''' ********优酷系统******** 1: 管理员 2: 普通用户 任意键退出 ''') choice = input('>>>请选择功能').strip() if choice in func_dict: func_dict.get(choice).run(client) else: print('告辞') break if __name__ == '__main__': run()
# _*_ coding: gbk _*_ # @Author: Wonder from lib import common import os import time from conf.settings import DOWNLOAD_PATH # 注册 current_user = {} def register(client): while True: username = input('请输入用户名').strip() password = input('请输入密码').strip() re_password = input('请再次输入密码').strip() if not password == re_password: print('密码不一致') continue dic = { 'func_type': 'register', 'username': username, 'password': password, 'user_type': 0 } back_dic = common.send_and_back(dic, client) if back_dic.get('flag'): print(back_dic.get('msg')) break else: print(back_dic.get('msg')) def login(client): while True: username = input('>>>请输入用户名').strip() password = input('>>>请输入密码').strip() dic = { 'func_type': 'login', 'username': username, 'password': password, 'user_type': 0 } back_dic = common.send_and_back(dic, client) if back_dic.get('flag'): current_user['cookies'] = back_dic.get('session') # 登陆成功之后,server会将session返回。 current_user['u_id'] = back_dic.get('u_id') current_user['is_vip'] = back_dic.get('is_vip') print(back_dic.get('msg')) break else: print(back_dic.get('msg')) # 充会员 def pay_member(client): # 此处是永久会员,修改is_vip pay = input('请确认开通vip,按y确认').strip() if not pay == 'y': print('再见,未开通') else: dic = { 'func_type': 'pay_member', 'is_vip': 1, 'cookies': current_user.get('cookies') } back_dic = common.send_and_back(dic, client) print(back_dic.get('msg')) # 查看电影目录 def check_movie(client): # 查看所有未删除的电影 dic = { 'func_type': 'check_nodel_movie', 'cookies': current_user.get('cookies'), 'select_type': 'all' } back_dic = common.send_and_back(dic, client) if back_dic.get('flag'): print(back_dic.get('mv_list')) else: print(back_dic.get('msg')) # 下载免费电影 def download_free_mv(client): # 先查免费电影的列表以供选择 while True: dic1 = { 'func_type': 'check_nodel_movie', 'cookies': current_user.get('cookies'), 'select_type': 'free' } back_dic = common.send_and_back(dic1, client) if not back_dic.get('flag'): print(back_dic.get('msg')) break # 封装一个方法,用于来选择。 free_mv_list = back_dic.get('mv_list') flag, msg = common.show_and_choice(free_mv_list) if not flag: # 输入了无效指令 continue else: # 接下来发送下载的请求 mv_name = msg dic2 = { 'func_type': 'download_mv', 'cookies': current_user.get('cookies'), 'mv_name': mv_name } back_dic = common.send_and_back(dic2, client) # 给出文件的大小 mv_size = back_dic.get('mv_size') mv_file = os.path.join(DOWNLOAD_PATH, mv_name) temp_size = 0 with open(mv_file, 'wb') as f: while temp_size < mv_size: data = client.recv(1024) f.write(data) temp_size += len(data) print('下载完毕......') break # 下载付费电影(要么充值会员,要么付费观影) def download_paid_mv(client): while True: # 付费电影,对普通用户有限制 先获取当前用户 if not current_user.get('is_vip'): print('当前用户不可以下载付费电影') pay_choice = input('press A去充会员,press B付费下载,任意键退出') if pay_choice == 'A': pay_member(client) login(client) break elif pay_choice == 'B': money = input('>>>充值的钱').strip() print('广告时间...5秒') time.sleep(5) else: break # 此处可以扩展付费模块,钱包功能。 dic = { 'func_type': 'check_nodel_movie', 'select_type': 'pay', 'cookies': current_user.get('cookies') } back_dic = common.send_and_back(dic, client) if not back_dic.get('flag'): print(back_dic.get('msg')) break else: pay_mv_list = back_dic.get('mv_list') flag, msg = common.show_and_choice(pay_mv_list) if not flag: print(msg) break else: movie_name = msg dic2 = { 'func_type': 'download_mv', 'cookies': current_user.get('cookies'), 'mv_name': movie_name } back_dic = common.send_and_back(dic2, client) mv_size = back_dic.get('mv_size') temp_size = 0 file_path = os.path.join(DOWNLOAD_PATH, movie_name) with open(file_path, 'wb') as f: while temp_size < mv_size: data = client.recv(1024) f.write(data) temp_size += len(data) print('下完了') # 这句话是否要从服务端传过来 break # 查看下载记录 def check_record(client): dic = { 'func_type': 'check_record', 'cookies': current_user.get('cookies'), } back_dic = common.send_and_back(dic, client) if not back_dic.get('flag'): print(back_dic.get('msg')) else: print(back_dic.get('mv_list')) # 查看公告 def check_notice(client): dic = { 'func_type': 'check_notice', 'cookies': current_user.get('cookies') } back_dic = common.send_and_back(dic, client) if not back_dic.get('flag'): print(back_dic.get('msg')) else: print(back_dic.get('notice_list')) def run(client): func_dic = { '1': register, '2': login, '3': pay_member, '4': check_movie, '5': download_free_mv, '6': download_paid_mv, '7': check_record, '8': check_notice, } while True: print(''' ********普通用户界面******** 1 注册 2 登录 3 冲会员 4 查看视频 5 下载免费视频 6 下载收费视频 7 查看下载记录 8 查看公告 q.退出 ''') choice = input('>>>请选择功能对应的编号').strip() if choice == 'q': print('再见') break if choice in func_dic: func_dic.get(choice)(client) else: print('无效指令')
# _*_ coding: gbk _*_ # @Author: Wonder import json import struct import os from hashlib import md5 from tcp_client.client import connect # 发数据 def send_and_back(dic, client, path=None): # 一次请求一次响应 send_dic = json.dumps(dic).encode('utf-8') send_head = struct.pack('i', len(send_dic)) client.send(send_head) client.send(send_dic) if path: with open(path, 'rb') as f: for line in f: client.send(line) head2 = client.recv(4) back_size = struct.unpack('i', head2)[0] back_dic = json.loads(client.recv(back_size).decode('utf-8')) return back_dic # 查看列表数据并进行选择 def show_and_choice(li): for index, content in enumerate(li): print(index, content) choice = input('请输入选择的电影序号').strip() if not choice.isdigit(): return False, '无效指令' choice = int(choice) if choice not in range(len(li)): return False, '无效指令' return True, li[choice] def get_movie_md5(path): movie_size = os.path.getsize(path) list_md5 = [0, movie_size // 2, movie_size - 10] with open(path, 'rb') as f: for index in list_md5: md5_obj = md5() f.seek(index) part = f.read(10) md5_obj.update(part) return md5_obj.hexdigest()
# _*_ coding: gbk _*_ # @Author: Wonder import socket from conf.settings import IP, PORT def connect(): client = socket.socket() client.connect((IP, PORT)) return client
# _*_ coding: gbk _*_ # @Author: Wonder import sys from conf import settings from core import src sys.path.append(settings.BASE_PATH) if __name__ == '__main__': src.run()