from flask import request, Blueprint from flask.wrappers import Response from flask_restful import Resource, Api from os import path, remove, walk, mkdir import logging import re from models.config import CONTENT_DIR, STATIC_DIR import shutil contents_app = Blueprint('contents', __name__) api = Api(contents_app) logger = logging.getLogger(__name__) DATA_FIELD = ['title:', 'url:','tags:','image:','description:'] def _get_data(file_dir): def load_data(): if 'title: ' in line: data_field.remove('title:') s = line.split('"') result['title'] = s[1] elif 'date: ' in line: # data_field.remove('date: ') s = line.replace('date: ', '').strip() result['date'] = s elif 'draft: ' in line: # data_field.remove('draft: ') s = line.replace('draft: ', '').strip() result['draft'] = s elif 'url: ' in line: data_field.remove('url:') s = line.split('"') result['url'] = s[1] elif 'tags: ' in line: data_field.remove('tags:') s = line.replace('tags: ', '').strip() """ if s != "": s = s + "," s = s + "全部屋型,全部坪數,全部預算,全部格局" """ result['tags'] = s elif 'image: ' in line: s = line.replace('image: ', '').strip() s = s.replace('"', '').strip() result['image'] = s elif 'description: ' in line: s = line.replace('description: ', '').strip() s = s.replace('"', '').strip() result['description'] = s data_field = list(DATA_FIELD) result = {} with open(file_dir, 'r', encoding="utf-8") as md: result['content'] = md.read() md.seek(0) md_line_data = md.readlines() for line in md_line_data: load_data() if not data_field: return result if not 'tags' in result: result['tags'] = "全部類型,全部坪數,全部預算,全部格局" else: if result['tags'] != "": result['tags'] = result['tags'] + "," result['tags'] = result['tags'].replace('"', '') + "全部類型,全部坪數,全部預算,全部格局" return result def _gen_content_files(): for root, dirs, files in walk(CONTENT_DIR): for f in files: if '.md' not in f: continue yield path.join(root, f) def _search_dir(url): def _get_file_front_matter_url(): with open(file_dir, 'r', encoding="utf-8") as md: md_line_data = md.readlines() for line in md_line_data: if 'url:' in line: return list(filter(None, re.split('"|\n', line)))[-1] for file_dir in _gen_content_files(): if url == _get_file_front_matter_url(): return path.dirname(file_dir) def _search_content_dir(type_, categories=None): target = categories or type_ def _get_file_front_matter_type(): with open(file_dir, 'r', encoding="utf-8") as md: md_line_data = md.readlines() for line in md_line_data: if categories: if 'categories' in line: return list(filter(None, re.split('"|\n|]', line)))[-1] else: if 'type:' in line: return list(filter(None, re.split('"|\n', line)))[-1] for file_dir in _gen_content_files(): if target == _get_file_front_matter_type(): return path.dirname(file_dir) class Content(Resource): DATA_FIELD = ['title:', 'url:'] @property def url(self): return request.args.get('url', type=str) def _search_content(self): result = {} for file_dir in _gen_content_files(): data = _get_data(file_dir) if self.url in data.get('url', ''): result = data result['path'] = file_dir #print(result['path']) yield result def _get_contents(self): for file_dir in _gen_content_files(): yield _get_data(file_dir) def get(self): if self.url: sortedData = sorted(list(self._search_content()), key=lambda x:x['date'], reverse=True) return sortedData else: sortedData = sorted(list(self._get_contents()), key=lambda x:x['date'], reverse=True) return sortedData def post(self): try: file_dir = path.join( _search_dir(request.args.get('url', type=str)), 'index.md') md_content = request.json.get('content') with open(file_dir, 'w', encoding="utf-8") as md: md.write(md_content) return md_content except TypeError as err: logger.error( 'Content post failed with file_dir param contain None. error: {}'.format(err)) except OSError as err: logger.error( 'Content post failed with: {} is not exist{}'.format(file_dir, err)) except AttributeError as err: logger.error('Content post failed with AttributeError: {}'.format(err)) except Exception as err: logger.error('Content post failed with: {}'.format(err)) def delete(self): content_data = list(self._search_content()) file_dir = content_data[0].get('path') if path.exists(file_dir): # remove(file_dir) shutil.rmtree(file_dir[0:file_dir.replace('\\', '/').rfind('/')+1]) # print(file_dir[0:file_dir.replace('\\','/').rfind('/')+1]) logger.info('delete dir: {}'.format( file_dir[0:file_dir.replace('\\', '/').rfind('/')+1])) else: logger.warning('delete fail with {} not exist'.format(file_dir)) @contents_app.route('/api/upload/img', methods=['POST']) def upload_img(): img_data = request.files['image'] file_dir = _search_dir(request.args.get('url', type=str)) img_dir = path.join(file_dir, 'img/{}'.format(img_data.filename)) img_data.save(img_dir) return {'filename': img_data.filename} @contents_app.route('/api/delete/img', methods=['DELETE']) def delete_img(): try: file_dir = _search_dir(request.args.get('url', type=str)) img_dir = path.join(file_dir, 'img/{}'.format(request.args.get('filename', type=str))) remove(img_dir) logger.info('delete img: {}'.format(img_dir)) return {'filename': request.args.get('filename', type=str)} except TypeError as err: logger.error('delete img: {} failed with file_dir is None. error: {}'.format( request.args.get('filename', type=str), err)) return {'filename': request.args.get('filename', type=str)} except OSError as err: logger.error('delete img: {} failed with img_dir is not exist. error: {}'.format( request.args.get('filename', type=str), err)) return {'filename': request.args.get('filename', type=str)} except Exception as err: logger.error('delete img: {} failed with {}'.format( request.args.get('filename', type=str), err)) return {'filename': request.args.get('filename', type=str)} @contents_app.route('/api/upload/static/img', methods=['POST']) def upload_static_img(): img_data = request.files['image'] img_dir = path.join(STATIC_DIR, 'img', request.args.get('type', type=str), request.args.get('filename', type=str)) img_data.save(img_dir) return {'filename': request.args.get('filename', type=str)} @contents_app.route('/api/new_content', methods=['POST']) def gen_content(): front_matter = request.json.get('frontMatter', '---\n---') name = request.json.get('name', 'Undefind') if request.json.get('type') == "blog": dir_ = CONTENT_DIR + "/"+request.json.get('type') + "/" + name if not path.exists(dir_): mkdir(dir_) if not path.exists(path.join(dir_, 'img')): mkdir(path.join(dir_, 'img')) with open(path.join(dir_, 'index.md'), 'w', encoding="utf-8") as md: md.write(front_matter) # print(front_matter) else: dir_ = path.join(_search_content_dir( request.json.get('type'), request.json.get('categories')), name) if dir_: if not path.exists(dir_): mkdir(dir_) else: return Response({}, status=201) if not path.exists(path.join(dir_, 'img')): mkdir(path.join(dir_, 'img')) with open(path.join(dir_, 'index.md'), 'w', encoding="utf-8") as md: md.write(front_matter) return {'new_content': name} @contents_app.route('/api/get_cats', methods=['POST', 'GET']) def get_cats(): """ front_matter = request.json.get('frontMatter', '---\n---') name = request.json.get('name', 'Undefind') dir_ = path.join(_search_content_dir( request.json.get('type'), request.json.get('categories')), name) """ #print(_search_content_dir('blog', 'home_inspection_knowledge')) return {} @contents_app.route('/api/new_cat', methods=['POST']) def gen_cat(): front_matter = request.json.get('frontMatter', '---\n---') name = request.json.get('name', 'Undefind') dir_ = path.join(_search_content_dir( request.json.get('type'), request.json.get('categories')), name) #print(request.json.get('type') + ',' + request.json.get('categories')) if dir_: if not path.exists(dir_): mkdir(dir_) else: return Response({}, status=201) if not path.exists(path.join(dir_, 'img')): mkdir(path.join(dir_, 'img')) with open(path.join(dir_, 'index.md'), 'w', encoding="utf-8") as md: md.write(front_matter) return {'new_content': name} api.add_resource(Content, '/api/contents')