import magic from flask import Blueprint, request, abort from google.protobuf.message import DecodeError from utils import pgclass, setting_loader, dbhelper from utils.misc import internal_json2protobuf, error_proto from protobuf_files import niming_pb2 # prefix: /article bl_article = Blueprint('article', __name__) ######################### # Article # ######################### # 匿名文列表 @bl_article.route('/list', methods = ["GET"]) def listing(): res, code = dbhelper.multi_article_fetcher("general", request.args.get("page"), 30) return res, code # 這裡要改 # 獲取匿名文附檔 @bl_article.route("/file/", methods=["GET"]) def getfile(fnhash:str): resp, code = dbhelper.solo_file_fetcher("general", fnhash) return resp, code # 獲取指定文章 @bl_article.route("/", methods = ["GET"]) def getarticle(id:int): resfn, code = dbhelper.solo_article_fetcher("general", key=id) if code == 200: return internal_json2protobuf(role="general", otype='a', original=[resfn]), code return abort(code) ######################### # Post(Article/Comment) # ######################### @bl_article.route("/", methods = ["POST"]) def posting(): """ Work Flow: ctx -> reference -> file -> post( hash -> IP -> IG -> mark ) | -> log """ # loadset opt = setting_loader.loadset() maxword = opt["Niming_Max_Word"] # protobuf parse recv = niming_pb2.Post() try: recv.ParseFromString(request.data) except DecodeError: return error_proto("Failed to parse data"), 400 # content and check content = str(recv.content) if len(content) == 0 or len(content) > maxword: # length check return error_proto("No content or too many words"), 400 # reference and check ref = int(recv.ref) if ref != 0: # 檢查指向的文章是否存在 且 可訪問 with dbhelper.db.getsession() as session: article = pgclass.SQLarticle article_mark = pgclass.SQLmark tpid = session.query(article.id).join(article_mark, article.hash==article_mark.hash) \ .filter(article.id==ref, article_mark.mark=="visible").first() if not tpid: return error_proto("Invalid Reference"), 400 else: ref = None result_id, sha1, hash = 0, "", "" if ref is None: # only article (comment dont have files) # file processing & check files = recv.files # check - size atts = opt["Attachment_Count"] sizelimit = opt["Attachment_Size"] if len(files) > atts: return error_proto("Too many files"), 400 for f in files: if len(f) <= 0 or len(f) > sizelimit: return error_proto("Empty file or file too big"), 400 # check - mimetype allowed_mime = opt["Allowed_MIME"] fmimes = [] for f in files: mime = magic.Magic(mime=True) type = mime.from_buffer(f) if not(type in allowed_mime): return error_proto("File type not allowed"), 400 fmimes.append(type) # posting result_id, hash = dbhelper.solo_article_uploader(content=content, file_list=files, fmimes=fmimes) if not result_id: return error_proto("Failed to Post"), 400 else: # comments sha1, hash = dbhelper.solo_comment_uploader(content=content, ref=ref) if not sha1: return error_proto("Failed to Post"), 400 # to protobuf & return proto_stres = niming_pb2.PostResponse( status = niming_pb2.Status.Success, hash = hash, id = int(result_id) ).SerializeToString() return proto_stres, 200