예제 #1
0
파일: plugin.py 프로젝트: zhantong/penguin
def send_mail(recipient, subject, body, message_id):
    message = Message.query.get(message_id)
    api_base_url = get_setting('api_base_url').value
    if not is_authorized():
        return
    token_type = get_setting('token_type').value
    access_token = get_setting('access_token').value
    request = urllib.request.Request(api_base_url + '/me/messages',
                                     data=json.dumps({
                                         'subject':
                                         subject,
                                         'body': {
                                             'contentType': 'HTML',
                                             'content': body
                                         },
                                         'toRecipients': [{
                                             'emailAddress': {
                                                 'address': recipient
                                             }
                                         }]
                                     }).encode(),
                                     method='POST')
    request.add_header('Authorization', token_type + ' ' + access_token)
    request.add_header('Content-Type', 'application/json')
    with urllib.request.urlopen(request) as f:
        result = json.loads(f.read().decode())
        message_id = result['id']
        web_link = result['webLink']
        message.message_id = message_id
        message.status = '草稿'
        message.web_link = web_link
        db.session.commit()
    if not is_authorized():
        return
    request = urllib.request.Request(api_base_url + '/me/messages/' +
                                     message_id + '/send',
                                     method='POST')
    request.add_header('Authorization', token_type + ' ' + access_token)
    request.add_header('Content-Length', '0')
    with urllib.request.urlopen(request) as f:
        code = f.code
        if code == 202:
            message.status = '已发送'
            db.session.commit()
    if not is_authorized():
        return
    request = urllib.request.Request(api_base_url + 'me/messages/' +
                                     message_id)
    request.add_header('Authorization', token_type + ' ' + access_token)
    request.add_header('Prefer', 'outlook.body-content-type="html"')
    with urllib.request.urlopen(request) as f:
        result = json.loads(f.read().decode())
        sent_date_time = result['sentDateTime']
        recipient = result['toRecipients'][0]['emailAddress']['address']
        web_link = result['webLink']
        message.sent_date_time = datetime.strptime(sent_date_time,
                                                   '%Y-%m-%dT%H:%M:%SZ')
        message.recipient = recipient
        message.web_link = web_link
        db.session.commit()
예제 #2
0
파일: plugin.py 프로젝트: zhantong/penguin
def authorize():
    token_url = get_setting('token_url').value
    client_id = get_setting('client_id').value
    scope = get_setting('scope').value
    redirect_url = get_setting('redirect_url').value
    client_secret = get_setting('client_secret').value

    code = request.args['code']
    with urllib.request.urlopen(token_url,
                                data=urllib.parse.urlencode({
                                    'client_id':
                                    client_id,
                                    'grant_type':
                                    'authorization_code',
                                    'scope':
                                    scope,
                                    'code':
                                    code,
                                    'redirect_uri':
                                    redirect_url,
                                    'client_secret':
                                    client_secret
                                }).encode()) as f:
        result = json.loads(f.read().decode())
        set_setting('access_token', value=result['access_token'])
        set_setting('token_type', value=result['token_type'])
        set_setting('expires_at',
                    value=str(int(time.time()) + result['expires_in']))
        set_setting('refresh_token', value=result['refresh_token'])
        opener.addheaders = [
            ('Authorization',
             result['token_type'] + ' ' + result['access_token'])
        ]
    return redirect(plugin_url_for('me', _component='admin'))
예제 #3
0
파일: plugin.py 프로젝트: zhantong/penguin
def login():
    authorize_url = get_setting('authorize_url').value
    client_id = get_setting('client_id').value
    scope = get_setting('scope').value
    redirect_url = get_setting('redirect_url').value

    return redirect(authorize_url + '?' +
                    urllib.parse.urlencode({
                        'client_id': client_id,
                        'response_type': 'code',
                        'redirect_uri': redirect_url,
                        'response_mode': 'query',
                        'scope': scope
                    }))
예제 #4
0
파일: api.py 프로젝트: zhantong/penguin
def admin_articles():
    def get_articles(repository_id):
        return Article.query.filter_by(repository_id=repository_id).order_by(
            Article.version_timestamp.desc()).all()

    page = request.args.get('page', 1, type=int)
    query = db.session.query(Article.repository_id).order_by(
        func.max(Article.version_timestamp).desc()).group_by(
            Article.repository_id)
    query = {'query': query}
    filter(query, request.args)
    query = query['query']
    pagination = query.paginate(page,
                                per_page=get_setting('items_per_page').value,
                                error_out=False)
    repository_ids = [item[0] for item in pagination.items]
    return {
        'value': [{
            'repositoryId':
            repository_id,
            'articles': [
                article.to_json('admin_brief')
                for article in get_articles(repository_id)
            ]
        } for repository_id in repository_ids]
    }
예제 #5
0
파일: plugin.py 프로젝트: zhantong/penguin
def list_tags():
    if request.method == 'POST':
        if request.form['action'] == 'delete':
            result = delete(request.form['id'])
            return jsonify(result)
    else:
        page = request.args.get('page', 1, type=int)
        pagination = Comment.query.order_by(desc(Comment.timestamp)).paginate(
            page,
            per_page=get_setting('items_per_page').value,
            error_out=False)
        comments = pagination.items
        return current_plugin.render_template(
            'list.html',
            comments=comments,
            get_comment_show_info=get_comment_show_info,
            pagination={
                'pagination': pagination,
                'fragment': {},
                'url_for': plugin_url_for,
                'url_for_params': {
                    'args': ['list'],
                    'kwargs': {
                        '_component': 'admin'
                    }
                }
            })
예제 #6
0
파일: plugin.py 프로젝트: zhantong/penguin
def get_admin_widget_article_list(params):
    def get_articles(repository_id):
        return Article.query.filter_by(repository_id=repository_id).order_by(
            Article.version_timestamp.desc()).all()

    page = 1
    if 'page' in params:
        page = int(params['page'])
    query = db.session.query(Article.repository_id).group_by(
        Article.repository_id).order_by(Article.version_timestamp.desc())
    query = {'query': query}
    filter(query, request.args)
    query = query['query']
    pagination = query.paginate(page,
                                per_page=get_setting('items_per_page').value,
                                error_out=False)
    repository_ids = [item[0] for item in pagination.items]
    custom_columns = Signal.send('custom_list_column')
    return current_plugin.render_template('list.html',
                                          repository_ids=repository_ids,
                                          pagination={
                                              'pagination': pagination,
                                              'fragment': {},
                                              'url_for': plugin_url_for,
                                              'url_for_params': {
                                                  'args': ['list'],
                                                  'kwargs': {
                                                      '_component': 'admin'
                                                  }
                                              }
                                          },
                                          get_articles=get_articles,
                                          custom_columns=custom_columns)
예제 #7
0
def dispatch():
    if request.method == 'POST':
        if request.form['action'] == 'delete':
            result = delete(request.form['id'])
            return jsonify(result)
    else:
        page = request.args.get('page', 1, type=int)
        pagination = Tag.query.order_by(Tag.name).paginate(
            page,
            per_page=get_setting('items_per_page').value,
            error_out=False)
        tags = pagination.items
        return current_plugin.render_template(
            'list.html',
            tags=tags,
            pagination={
                'pagination': pagination,
                'fragment': {},
                'url_for': plugin_url_for,
                'url_for_params': {
                    'args': ['list'],
                    'kwargs': {
                        '_component': 'admin'
                    }
                }
            },
            admin_article_list_url=admin_article_list_url)
예제 #8
0
파일: plugin.py 프로젝트: zhantong/penguin
def admin_api_proxy(widget, path, request, article):
    if widget == 'attachment':
        if request.method == 'POST':
            data = request.get_json()
            filename = data['filename']
            if '.' not in filename or filename.rsplit('.', 1)[1].lower(
            ) not in get_setting('allowed_upload_file_extensions').value:
                return jsonify({'message': '禁止上传的文件类型'}), 400
            extension = filename.rsplit('.', 1)[1].lower()
            random_filename = uuid.uuid4().hex + '.' + extension
            abs_file_path = os.path.join(current_app.config['TEMP_FOLDER'],
                                         random_filename)
            os.makedirs(os.path.dirname(abs_file_path), exist_ok=True)
            with open(abs_file_path, 'wb') as f:
                f.write(base64.b64decode(data['base64']))
            attachment = Attachment.create(abs_file_path,
                                           original_filename=filename,
                                           file_extension=extension)
            db.session.add(attachment)
            article.attachments.append(attachment)
            db.session.commit()
            return jsonify({'id': attachment.id}), 201
        if request.method == 'DELETE':
            splits = path.split('/')
            attachment_id = int(splits[1])
            attachment = Attachment.query.get(attachment_id)
            db.session.delete(attachment)
            db.session.commit()
            return jsonify({'message': '删除成功'})
    if widget == 'attachments':
        if request.method == 'GET':
            return {
                'value':
                [attachment.to_json() for attachment in article.attachments]
            }
예제 #9
0
파일: plugin.py 프로젝트: zhantong/penguin
def list_messages():
    if request.method == 'POST':
        if request.form['action'] == 'resend':
            comment_id = request.form['comment_id']
            comment_submitted(sender=None,
                              comment=Comment.query.get(comment_id))
        elif request.form['action'] == 'rerun':
            job_id = request.form['job_id']
            redis_url = current_app.config['REDIS_URL']
            with Connection(redis.from_url(redis_url)):
                fq = get_failed_queue()
                fq.requeue(job_id)
    else:
        page = request.args.get('page', 1, type=int)
        pagination = Message.query.paginate(
            page,
            per_page=get_setting('items_per_page').value,
            error_out=False)
        messages = pagination.items
        with Connection(redis.from_url(current_app.config['REDIS_URL'])):
            queue = Queue()
        return current_plugin.render_template('list.html',
                                              messages=messages,
                                              queue=queue,
                                              pagination={
                                                  'pagination': pagination,
                                                  'fragment': {},
                                                  'url_for': plugin_url_for,
                                                  'url_for_params': {
                                                      'args': ['list'],
                                                      'kwargs': {
                                                          '_component': 'admin'
                                                      }
                                                  }
                                              })
예제 #10
0
파일: plugin.py 프로젝트: zhantong/penguin
def main_widget(request):
    def get_metas(article):
        return Signal.send('article_list_item_meta', article=article)

    page = request.args.get('page', 1, type=int)
    query = Article.query_published().order_by(Article.timestamp.desc())
    query = {'query': query}
    filter(query, request.args)
    query = query['query']
    pagination = query.paginate(page,
                                per_page=get_setting('items_per_page').value,
                                error_out=False)
    articles = pagination.items
    return {
        'slug':
        'article_list',
        'name':
        '文章列表',
        'html':
        current_plugin.render_template('widget_article_list',
                                       'widget.html',
                                       articles=articles,
                                       pagination=pagination,
                                       request_params=request.args,
                                       get_metas=get_metas)
    }
예제 #11
0
def get_navbar_item():
    return {
        'type':
        'brand',
        'brand':
        get_setting('site_name').value,
        'more': [{
            'type': 'item',
            'name': '首页',
            'link': component_url_for('index')
        }]
    }
예제 #12
0
파일: plugin.py 프로젝트: zhantong/penguin
def is_authorized():
    access_token = get_setting('access_token').value
    if access_token == '':
        return False
    expires_at = get_setting('expires_at').value
    if expires_at - 10 < int(time.time()):
        token_url = get_setting('token_url').value
        refresh_token = get_setting('refresh_token').value
        client_id = get_setting('client_id').value
        redirect_url = get_setting('redirect_url').value
        scope = get_setting('scope').value
        client_secret = get_setting('client_secret').value
        if refresh_token == '':
            return False
        with urllib.request.urlopen(token_url,
                                    data=urllib.parse.urlencode({
                                        'client_id':
                                        client_id,
                                        'grant_type':
                                        'refresh_token',
                                        'scope':
                                        scope,
                                        'refresh_token':
                                        refresh_token,
                                        'redirect_uri':
                                        redirect_url,
                                        'client_secret':
                                        client_secret
                                    }).encode()) as f:
            result = json.loads(f.read().decode())
            set_setting('access_token', value=result['access_token'])
            set_setting('token_type', value=result['token_type'])
            set_setting('expires_at',
                        value=str(int(time.time()) + result['expires_in']))
            set_setting('refresh_token', value=result['refresh_token'])
    token_type = get_setting('token_type').value
    access_token = get_setting('access_token').value
    opener.addheaders = [('Authorization', token_type + ' ' + access_token)]
    return True
예제 #13
0
파일: plugin.py 프로젝트: zhantong/penguin
def send_email(to_address, subject, content):
    from_address = get_setting('email').value
    password = get_setting('password').value
    smtp_address = get_setting('smtp_address').value

    msg = MIMEText(content, 'plain', 'utf-8')
    msg['From'] = _format_address(
        get_setting('site_name').value + from_address)
    msg['To'] = _format_address('%s <%s>' % (to_address, to_address))
    msg['Subject'] = Header(subject, 'utf-8').encode()

    log_file = tempfile.TemporaryFile()
    available_fd = log_file.fileno()
    log_file.close()
    os.dup2(2, available_fd)
    log_file = tempfile.TemporaryFile()
    os.dup2(log_file.fileno(), 2)

    try:
        smtp = smtplib.SMTP_SSL(smtp_address, 465)
        smtplib.stderr = log_file
        smtp.set_debuglevel(2)
        smtp.login(from_address, password)
        smtp.sendmail(from_address, [to_address], msg.as_string())
        smtp.quit()
    except smtplib.SMTPException as e:
        is_success = False
    else:
        is_success = True

    sys.stderr.flush()
    log_file.flush()
    log_file.seek(0)
    stderr_bytes = log_file.read()
    log_file.close()
    os.dup2(available_fd, 2)
    os.close(available_fd)

    return is_success, stderr_bytes.decode()
예제 #14
0
파일: plugin.py 프로젝트: zhantong/penguin
def me():
    if is_authorized():
        api_base_url = get_setting('api_base_url').value
        try:
            f = opener.open(api_base_url + '/me')
            me = json.loads(f.read().decode())
        except urllib.error.HTTPError as e:
            me = None
    else:
        me = None
    return current_plugin.render_template('me.html',
                                          me=me,
                                          login_url=plugin_url_for(
                                              'login', _component='admin'))
예제 #15
0
파일: plugin.py 프로젝트: zhantong/penguin
def upload():
    if 'files[]' not in request.files:
        return jsonify({'code': 1, 'message': '上传文件不存在'})
    file = request.files['files[]']
    if file.filename == '':
        return jsonify({'code': 2, 'message': '未选择上传文件'})
    filename = file.filename
    if '.' not in filename or filename.rsplit('.', 1)[1].lower(
    ) not in get_setting('allowed_upload_file_extensions').value:
        return jsonify({'code': 3, 'message': '禁止上传的文件类型'})
    extension = filename.rsplit('.', 1)[1].lower()
    random_filename = uuid.uuid4().hex + '.' + extension
    abs_file_path = os.path.join(current_app.config['TEMP_FOLDER'],
                                 random_filename)
    os.makedirs(os.path.dirname(abs_file_path), exist_ok=True)
    file.save(abs_file_path)
    attachment = Attachment.create(abs_file_path,
                                   original_filename=filename,
                                   file_extension=extension,
                                   mime=file.mimetype)
    db.session.add(attachment)
    db.session.commit()
    meta = json.loads(request.form.get('meta', type=str))
    if 'article_id' in meta:
        article = Signal.send('get_article',
                              'article',
                              article_id=meta['article_id'])
        article.attachments.append(attachment)
        db.session.commit()
    if 'page_id' in meta:
        page = Signal.send('get_page', 'page', page_id=meta['page_id'])
        page.attachments.append(attachment)
        db.session.commit()
    return jsonify({
        'code':
        0,
        'message':
        '上传成功',
        'file_size':
        attachment.file_size,
        'relative_path':
        random_filename,
        'delete_url':
        component_url_for('.upload_delete', 'admin', id=attachment.id)
    })
예제 #16
0
파일: api.py 프로젝트: zhantong/penguin
def articles():
    page = request.args.get('page', 1, type=int)
    query = Article.query_published().order_by(Article.timestamp.desc())
    query = {'query': query}
    filter(query, request.args)
    query = query['query']
    pagination = query.paginate(page,
                                per_page=get_setting('items_per_page').value,
                                error_out=False)
    articles = pagination.items
    return {
        'articles': [article.to_json('basic') for article in articles],
        'pagination': {
            'prevNum': pagination.prev_num,
            'nextNum': pagination.next_num,
            'page': pagination.page,
            'pages': pagination.pages,
            'perPage': pagination.per_page,
            'total': pagination.total
        }
    }
예제 #17
0
 def send(cls, _name, _scope, **kwargs):
     from bearblog.settings import get_setting
     signal_name = _scope + '.' + _name
     if signal_name not in cls._signals:
         return
     signal = cls._signals[signal_name]
     if 'return_type' in cls._signals[signal_name]:
         return_type = cls._signals[signal_name]['return_type']
         if return_type == 'single':
             for receiver in signal['receivers'].values():
                 item_result = cls.call_receiver_func(
                     receiver['func'], kwargs)
                 if item_result is not None:
                     return item_result
         if return_type == 'list':
             if not signal.get('managed', False):
                 result = []
                 for receiver in signal['receivers'].values():
                     result.append(
                         cls.call_receiver_func(receiver['func'], kwargs))
                 return result
             else:
                 result = []
                 signal_settings_obj = get_setting(_name, category=_scope)
                 if signal_settings_obj is None or 'subscribers_order' not in signal_settings_obj.value:
                     if signal['managed_default'] == 'all':
                         for receiver in signal.get('receivers',
                                                    {}).values():
                             result.append(
                                 cls.call_receiver_func(
                                     receiver['func'], kwargs))
                         return result
                     elif signal['managed_default'] == 'none':
                         return []
                 else:
                     signal_settings = signal_settings_obj.value
                     result = {}
                     for list_name, items in signal_settings[
                             'subscribers_order'].items():
                         result[list_name] = []
                         for item in items:
                             if item['is_on'] and item[
                                     'subscriber'] in signal['receivers']:
                                 receiver = signal['receivers'][
                                     item['subscriber']]['func']
                                 result[list_name].append(
                                     cls.call_receiver_func(
                                         receiver, kwargs))
                     if 'main' in result and len(result) == 1:
                         result = result['main']
                     return result
         if return_type == 'merged_list':
             result = []
             for receiver in signal['receivers'].values():
                 item_result = cls.call_receiver_func(
                     receiver['func'], kwargs)
                 if type(item_result) is list:
                     result.extend(item_result)
                 else:
                     result.append(item_result)
             return result
         if return_type == 'dict':
             result = {}
             for receiver in signal['receivers'].values():
                 key, value = cls.call_receiver_func(
                     receiver['func'], kwargs)
                 result[key] = value
             return result
         if return_type == 'single_not_none':
             for receiver in signal['receivers'].values():
                 item_result = cls.call_receiver_func(
                     receiver['func'], kwargs)
                 if item_result is not None:
                     return item_result
             raise ValueError()
     else:
         for receiver in signal['receivers'].values():
             cls.call_receiver_func(receiver['func'], kwargs)