def send_async_email(msg, html, text, attach=None, send_independently=True): """ 发送email :param subject: :param recipients:数组 :param text: :param html: :param attach:(<filename>,<content_type>) :param send_independently:如果为True, 独立给recipients中的每个地址发送信息, 否则,一次发送, 收件人能看到其他收件人的邮箱 :return: """ # 检测插件 data = plugin_manager.call_plug(hook_name="send_email", send_independently=send_independently, msg=msg, html=html, text=text, attach=attach) if data == "__no_plugin__": with app.app_context(): msg_obj = Message(subject=msg["subject"], html=html) if send_independently: # 独立发送, 先连接好邮件服务器 with mail.connect() as conn: for recipient in msg["recipients"]: msg_obj.recipients = [recipient] send_email_process(msg_obj, conn) else: msg_obj.recipients = msg["recipients"] return send_email_process(msg_obj)
def upload_file(file=None, prefix="", file_name=None, file_format=None, fetch_url=False, tailoring=None): ''' 文件保存 :param file, 上传文件对象 :param prefix: 给文件名加前缀, 如果prefix中有"/",则系统也会自动根据/来建目录 :param file_name:如果file_name是这样的post-img/xxxx-xxx-xxx.jpg,则系统也会自动根据/来建目录 :param file_format:文件格式,如:png :param tailoring:不建议使用此参数建议再客户端处理完上传 :return: ''' # 如果自定义名字 if file_name: filename = '{}.{}'.format(file_name, file_format) else: filename = '{}-{}.{}'.format(time_to_utcdate(time_stamp=time.time()), uuid1(), file_format) # 本地服务器 if prefix: filename = "{}{}".format(prefix, filename) # 文件保存的绝对路径 save_file_path = "{}/{}/{}".format(STATIC_PATH, get_config("upload", "SAVE_DIR"), filename).replace("//", "/") # 文件保存到本地服务器端 save_dir = os.path.split(save_file_path)[0] if not os.path.exists(save_dir): os.makedirs(save_dir) # 文件保存到本地服务器端 if fetch_url: urllib.request.urlretrieve(fetch_url, save_file_path) elif file: file.save(save_file_path) if tailoring: # 裁剪图片 try: im = Image.open(save_file_path) im = im.rotate(tailoring['rotate']) region = im.crop((tailoring["x"], tailoring["y"], tailoring["x"]+tailoring["width"], tailoring["y"]+tailoring["height"])) region.save(save_file_path) except : pass # 检测文件储存插件 data = plugin_manager.call_plug(hook_name="file_storage", action="upload", localfile_path=save_file_path, filename=filename) if data != "__no_plugin__": # 上传后删除本地文件 local_file_del(save_file_path) result = data else: result = {"key":filename, "bucket_name":None, "d":None, "type":"local"} return result
def get_file_url(file_url_obj, save_dir=get_config("upload", "SAVE_DIR")): """ 需要提供一个路径的对象 :param file_url_obj:可以是osroom的路径格式对象, 否则原对象返回 :return:file url """ if isinstance(file_url_obj, dict) and "key" in file_url_obj: # 检测上传插件 data = plugin_manager.call_plug(hook_name="file_storage", action="get_file_url", file_url_obj=file_url_obj) if data == "__no_plugin__": url = url_for('static', filename="{}/{}".format(save_dir, file_url_obj["key"])) else: url = data return url elif isinstance(file_url_obj, str): if not file_url_obj: file_url_obj = get_config("site_config", "DOES_NOT_EXIST_URL") return file_url_obj else: return get_config("site_config", "DOES_NOT_EXIST_URL")
def fileup_base_64(uploaded_files, file_name=None, prefix=""): ''' 文件以base64编码上传上传 :param uploaded_files: 数组 :param bucket_var: 保存图片服务器空间名的变量名, 如AVA_B :param file_name: :return: ''' if not uploaded_files: return None keys = [] for file_base in uploaded_files: if file_base: # data:image/jpeg file_format = file_base.split(";")[0].split("/")[-1] imgdata = base64.b64decode(file_base.split(",")[-1]) if file_name: filename = '{}.{}'.format(file_name, file_format) else: filename = '{}_{}.{}'.format(time_to_utcdate(time_stamp=time.time(), tformat="%Y%m%d%H%M%S"), uuid1(), file_format) # 本地服务器 if prefix: filename = "{}{}".format(prefix, filename) # 文件保存的绝对路径 save_file_path = "{}/{}/{}".format(STATIC_PATH, get_config("upload", "SAVE_DIR"), filename).replace("//", "/") # 文件保存到本地服务器端 save_dir = os.path.split(save_file_path)[0] if not os.path.exists(save_dir): os.makedirs(save_dir) with open(save_file_path, 'wb') as file_w: file_w.write(imgdata) # 检测文件储存插件 data = plugin_manager.call_plug(hook_name="file_storage", action="upload", localfile_path=save_file_path, filename=filename) if data != "__no_plugin__": # 上传后删除本地文件 local_file_del(save_file_path) key = data else: key = {"key": filename, "bucket_name": None, "d": None, "type": "local"} else: key = None keys.append(key) call_file_detection(keys) return keys
def send_async_email(msg, html, text, attach=None, send_independently=True, ctype="other"): """ 发送email :param subject: :param recipients:数组 :param text: :param html: :param attach:(<filename>,<content_type>) :param send_independently:如果为True, 独立给recipients中的每个地址发送信息, 否则,一次发送, 收件人能看到其他收件人的邮箱 :return: """ # 检测插件 data = plugin_manager.call_plug(hook_name="send_email", send_independently=send_independently, msg=msg, html=html, text=text, attach=attach) if data == "__no_plugin__": with app.app_context(): msg_obj = Message(subject=msg["subject"], html=html) if send_independently: # 独立发送, 先连接好邮件服务器 with mail.connect() as conn: for recipient in msg["recipients"]: msg_obj.recipients = [recipient] status, result_msg = send_email_process(msg_obj, conn) else: msg_obj.recipients = msg["recipients"] status, result_msg = send_email_process(msg_obj) log = { "type": "email", "error_info": result_msg, 'status': status, 'subject': msg_obj.subject, 'from': msg_obj.sender, 'to': list(msg["recipients"]), 'date': msg_obj.date, 'body': msg_obj.body, 'html': msg_obj.html, 'msgid': msg_obj.msgId, 'time': time.time(), 'msg_type': ctype } mdbs["sys"].db.sys_message.insert_one(log)
def reader_city(ip): ''' :param reader_obj: reader object :param ip: :return:a dict ''' # 检测插件 data = plugin_manager.call_plug(hook_name="ip_geo", ip=ip) if data == "__no_plugin__": return {} return data
def file_del(file_url_obj): """ 需要提供一个路径字典 :param file_url_obj: :return: """ # 检测插件 data = plugin_manager.call_plug(hook_name="file_storage", action="delete", file_url_obj=file_url_obj) if data == "__no_plugin__": path = get_localfile_path(file_url_obj=file_url_obj) return local_file_del(path=path)
def content_inspection_audio(url): """ 音频鉴定 :param url:音频url :return: """ if get_config("content_inspection", "AUDIO_OPEN"): # 调用内容审核插件 data = plugin_manager.call_plug("content_inspection_audio", url=url) if data == "__no_plugin__": if current_user.is_staff: return {"score": 0, "label": "no_plugin"} else: return {"score": 100, "label": "no_plugin"} else: return data else: return {"score": 0, "label": "detection_off"}
def content_inspection_image(url): ''' 图片鉴定 :param url:图片url :return: ''' if get_config("content_inspection", "IMAGE_OPEN"): # 调用内容审核插件 data = plugin_manager.call_plug("content_inspection_image", url=url) if data == "__no_plugin__": if current_user.is_staff: return {"score": 0, "label": "no_plugin"} else: return {"score": 100, "label": "no_plugin"} else: return data else: return {"score": 0, "label": "detection_off"}
def content_inspection_text(content): ''' 文本内容鉴定 :param content: :return: ''' if get_config("content_inspection", "TEXT_OPEN"): # 调用内容审核插件 data = plugin_manager.call_plug("content_inspection_text", content=content) if data == "__no_plugin__": if current_user.is_staff: return {"score":0, "label":"no_plugin"} else: return {"score":100, "label": "no_plugin"} else: return data else: return {"score": 0, "label": "detection_off"}
def send_email(subject, recipients, text_msg=None, html_msg=None, attach=None, send_independently=True): """ 发送email :param subject: :param recipients:数组 :param text_msg: :param html_msg: :param attach:(<filename>,<content_type>) :param send_independently:如果为True, 独立给recipients中的每个地址发送信息, 否则,一次发送, 收件人能看到其他收件人的邮箱 :return: """ # 检测插件 data = plugin_manager.call_plug(hook_name="send_email", recipients=recipients, send_independently=send_independently, subject=subject, html=html_msg, text=text_msg, attach=attach) if data == "__no_plugin__": msg = Message(subject=subject, sender=get_config("email", "MAIL_DEFAULT_SENDER")) if html_msg: msg.html = html_msg elif text_msg: msg.body = text_msg if attach and len(attach) == 2: with app.open_resource(attach[0]) as fp: msg.attach(os.path.split(attach[0])[-1], attach[1], fp.read()) # send email send_async_email(app, msg, recipients=recipients, send_independently=send_independently)
def send_mobile_msg(numbers, content): """ 短信发送 :param numbers:数组 :param content: :return: """ # 检测插件 data = plugin_manager.call_plug(hook_name="send_msg", to_numbers=numbers, content=content) msg = None if data == "__no_plugin__": msg = gettext( "There is no plug-in for sending SMS messages to mobile phones," " please install the relevant plug-in") status = "abnormal" result = (False, msg) elif not data: status = "abnormal" result = (False, gettext("Failed to send")) else: status = "normal" result = (True, gettext("SMS sent successfully")) log = { "type": "sms", "error_info": msg, 'status': status, 'subject': "", 'from': "", 'to': numbers, 'date': time.time(), 'body': content, 'html': "", 'msgid': None, 'time': time.time() } mdbs["sys"].db.sys_message.insert_one(log) return result
def file_rename(file_url_obj, new_filename): """ 需要提供一个本系统定义的文件字典 :param filedict: :return: """ # 检测插件 data = plugin_manager.call_plug(hook_name="file_storage", action="delete", file_url_obj=file_url_obj, new_filename=new_filename) if data == "__no_plugin__": path = get_localfile_path(file_url_obj=file_url_obj) file_format = os.path.splitext(path)[-1] new_path = "{}/{}{}".format( os.path.split(path)[0], os.path.split(path)[1], file_format) os.rename(path, new_path) return True else: return data
def copy_file(from_file_url_obj=None, from_path=None, replica_prefix="", replica_file_name=None, replica_file_format=None): """ 文件复制,同一个区域的文件才可以复制 :param file_url_obj:和from_path二选1 :param from_path: :param replica_prefix: :param replica_file_name: :param replica_file_format: :return: """ # 如果自定义名字 if replica_file_name: filename = '{}.{}'.format(replica_file_name, replica_file_format) else: filename = '{}-{}.{}'.format(time_to_utcdate(time_stamp=time.time()), uuid1(), replica_file_format) if replica_prefix: filename = "{}{}".format(replica_prefix, filename) filename = filename.replace("//", "/") if from_file_url_obj: if from_file_url_obj['type'] == "local": # 是复制本地图片 from_local_path = get_localfile_path(from_file_url_obj) # 文件保存的绝对路径 save_file_path = "{}/{}/{}".format( STATIC_PATH, get_config("upload", "SAVE_DIR"), filename).replace("//", "/") # 文件保存到本地服务器端 save_dir = os.path.split(save_file_path)[0] if not os.path.exists(save_dir): os.makedirs(save_dir) shutil.copyfile(from_local_path, save_file_path) result = { "key": filename, "bucket_name": None, "d": None, "type": "local" } return result else: # 检图床插件 data = plugin_manager.call_plug(hook_name="file_storage", action="copy_file", file_url_obj=from_file_url_obj, filename=filename) if data == "__no_plugin__": return None else: return data elif from_path: # 检图床插件 data = plugin_manager.call_plug( hook_name="file_storage", action="upload", localfile_path=from_path, filename=filename, ) if data == "__no_plugin__": # 文件保存的绝对路径 save_file_path = "{}/{}/{}".format( STATIC_PATH, get_config("upload", "SAVE_DIR"), filename).replace("//", "/") # 文件保存到本地服务器端 save_dir = os.path.split(save_file_path)[0] if not os.path.exists(save_dir): os.makedirs(save_dir) shutil.copyfile(from_path, save_file_path) result = { "key": filename, "bucket_name": None, "d": None, "type": "local" } return result else: return data
def create_img_code(interference=0): ''' 生成验证码 difficulty: 数值越高, 越难辨别,最小为10 :return: ''' # 240 x 60: # 每次生成验证码的同时,我们删除本地过期验证码 vercode_del(expiration_time=get_config("verify_code", "EXPIRATION")) max_in = get_config("verify_code", "MAX_IMG_CODE_INTERFERENCE") min_in = get_config("verify_code", "MIN_IMG_CODE_INTERFERENCE") if interference < 10: if min_in < 10: min_in = 10 if min_in > max_in: temp_max_in = max_in max_in = min_in min_in = temp_max_in else: min_in = 10 max_in = 30 interference = random.randint(min_in, max_in) # 验证码尺寸 width = 60 * 4 height = 60 pic = CreateImgCode(width, height, 'white') pic.create_pic() pic.create_point(interference * 50) pic.create_line(interference * 3) # 生成随机码写入 _str = "" for t in range(4): c = random_char() _str = "{}{}".format(_str, c) pic.create_text(FONT_PATH, 24, _str) # 扭曲 # pic.istortion_shift() # 保存路径 local_dirname = get_config("upload", "IMG_VER_CODE_DIR") save_dir = "{}/{}".format(STATIC_PATH, local_dirname).replace("//", "/") if not os.path.exists(save_dir): os.makedirs(save_dir) code_img = '{}__{}.jpg'.format(time.time(), uuid1()) save_img = '{}/{}'.format(save_dir, code_img) # 保存 pic.img.save(save_img, 'jpeg') # 检图床插件 data = plugin_manager.call_plug(hook_name="file_storage", action="upload", localfile_path=save_img, filename=code_img) if data == "__no_plugin__": code_url_info = {"key": code_img, "type": "local"} else: code_url_info = data # 使用了第三方插件存储,则删除本地验证码 local_file_del(path=save_img) _code = { 'url': code_url_info, 'str': _str, 'time': time.time(), "type": "image" } mdb_web.db.verify_code.insert_one(_code) _code.pop('_id') _code.pop('str') _code['img_url_obj'] = _code['url'] _code['url'] = get_file_url(code_url_info, save_dir=local_dirname) return _code
def third_party_sign_in(platform_name): ''' 第三方登录回调函数 :param hook_name: 第三方登录钩子名称,如:"wechat_login" :return: ''' # 检测插件 data = plugin_manager.call_plug(hook_name="{}_login".format(platform_name), request_argget_all=request.argget.all) if data == "__no_plugin__": data = {"msg":gettext("No login processing plugin for this platform, please install the relevant plugin first"), "msg_type":"e", "http_status":400} return data unionid = data.get("unionid") # 检测用户是否等录过 query = { "login_platform.{}.unionid".format(platform_name):unionid } user = mdb_user.db.user.find_one(query) if user: # 此用户已经在当前平台登录过, 直接登录 user = User(user["_id"]) if user.is_active: login_user(user, False) # 记录登录日志 login_log(user, client="unknown:{}".format(platform_name)) data = {"msg":gettext("Sign in success"), "msg_type":"s", "http_status":201} else: # 未激活 data = {"msg":gettext("Account is inactive or frozen"), "msg_type":"w", "http_status":401} else: # 第一次登录, 注册信息 # 用户基本信息 nickname = "{}_{}".format(data.get("nickname"),randint(10000000,99999999)) gender = data.get("gender") email = data.get("email") avatar_url = data.get("avatar_url") province = data.get("province") city = data.get("city") country = data.get("country") address = {"province":province, "city":city, "country":country} s, r = arg_verify(reqargs=[("unionid", unionid)], required=True) if not s: return r s, r = arg_verify(reqargs=[(gettext("gender"), gender)], only=["secret", "m", "f"]) if not s: return r role_id = mdb_user.db.role.find_one({"default": {"$in": [True, 1]}})["_id"] user = user_model( unionid=unionid, platform_name=platform_name, username=nickname, email=email, mphone_num=None, password=None, custom_domain=-1, address=address, avatar_url=avatar_url, role_id=role_id, active=True ) r = mdb_user.db.user.insert_one(user) if r.inserted_id: data = {'msg':gettext('Registered successfully'), 'to_url':'/sign-in', 'msg_type':'s',"http_status":201} else: data = {'msg': gettext('Data saved incorrectly, please try again'), 'msg_type': 'e', "http_status": 400} return data
def create_img_code(interference=0): """ 生成验证码 difficulty: 数值越高, 越难辨别,最小为10 :return: """ # 240 x 60: # 每次生成验证码的同时,我们删除本地过期验证码 vercode_del(expiration_time=get_config("verify_code", "EXPIRATION")) _str = "" for t in range(4): c = random_char() _str = "{}{}".format(_str, c) # 使用ImageCaptcha验证码生成程序 image = ImageCaptcha() image.generate(_str) # 保存路径 local_dirname = get_config("verify_code", "IMG_CODE_DIR") save_dir = "{}/{}".format(STATIC_PATH, local_dirname).replace("//", "/") if not os.path.exists(save_dir): os.makedirs(save_dir) code_img = '{}__{}.png'.format(time.time(), uuid1()) save_img = '{}/{}'.format(save_dir, code_img) image.write(_str, save_img) # osroom 验证码程序 # max_in = get_config("verify_code", "MAX_IMG_CODE_INTERFERENCE") # min_in = get_config("verify_code", "MIN_IMG_CODE_INTERFERENCE") # if interference < 10: # # if min_in < 10: # min_in = 10 # if min_in > max_in: # temp_max_in = max_in # max_in = min_in # min_in = temp_max_in # else: # min_in = 10 # max_in = 30 # interference = random.randint(min_in, max_in) # # # 验证码尺寸 # width = 60 * 4 # height = 60 # pic = CreateImgCode(width, height, 'white') # pic.create_pic() # pic.create_point(interference * 50) # pic.create_line(interference * 3) # 生成随机码写入 # _str = "" # for t in range(4): # c = random_char() # _str = "{}{}".format(_str, c) # pic.create_text(FONT_PATH, 24, _str) # # # 扭曲 # # pic.istortion_shift() # # 保存路径 # local_dirname = get_config("verify_code", "IMG_CODE_DIR") # save_dir = "{}/{}".format(STATIC_PATH, local_dirname).replace("//", "/") # if not os.path.exists(save_dir): # os.makedirs(save_dir) # code_img = '{}__{}.jpg'.format(time.time(), uuid1()) # save_img = '{}/{}'.format(save_dir, code_img) # # # 保存 # pic.img.save(save_img, 'jpeg') # 检图床插件 data = plugin_manager.call_plug(hook_name="file_storage", action="upload", localfile_path=save_img, filename="{}/{}".format( local_dirname, code_img)) if data == "__no_plugin__": code_url_info = {"key": code_img, "type": "local"} else: code_url_info = data # 使用了第三方插件存储,则删除本地验证码 local_file_del(path=save_img) _code = { 'url': code_url_info, 'str': _str, 'time': time.time(), "type": "image" } mdbs["web"].db.verify_code.insert_one(_code) _code.pop('_id') _code.pop('str') _code['img_url_obj'] = _code['url'] _code['url'] = get_file_url(code_url_info, save_dir=local_dirname) return _code