<commit_before>"""
ETLT

Copyright 2016 Set Based IT Consultancy

Licence MIT
"""
import copy
import datetime

class Type2Helper:
    """
    A helper class for reference data with date intervals.
    """

    # ------------------------------------------------------------------------------------------------------------------
    def __init__(self, key_start_date, key_end_date, natural_key):
        """
        Object constructor.

        :param str key_start_date: The key of the start date in the rows.
        :param str key_end_date: The key of the end date in the rows.
        :param list[str] natural_key: The keys of the columns that form the natural key.
        """
        self._natural_key = list(natural_key)
        """
        The keys of the columns that form the natural key.

        :type list[str]:
        """

        self._key_end_date = key_end_date
        """
        The key of the end date in the rows.

        :type str:
        """
        self._key_start_date = key_start_date
        """
        The key of the start date in the rows.

        :type str:
        """

        self.rows = dict()
        """
        The data set.

        :type dict:
        """

        self._date_type = ''
        """
        The type of the date fields.
        - date for datetime.date objects
        - str  for strings in ISO 8601 (YYYY-MM-DD) format.

        :type str:
        """

    # ------------------------------------------------------------------------------------------------------------------
    def _get_natural_key(self, row):
        """
        Returns the natural key in a row.

        :param dict row: The row.

        :rtype: tuple
        """
        ret = list()
        for key in self._natural_key:
            ret.append(row[key])

        return tuple(ret)

    # ------------------------------------------------------------------------------------------------------------------
    @staticmethod
    def _date2int(date):
        """
        Returns an integer representation of a date.

        :param str|datetime.date date: The date.

        :rtype: int
        """
        if isinstance(date, str):
            tmp = datetime.datetime.strptime(date, '%Y-%m-%d')
            return tmp.toordinal()

        if isinstance(date, datetime.date):
            return date.toordinal()

        if isinstance(date, int):
            return date

        raise ValueError('Unexpected type {0!s}'.format(date.__class__))

    # ------------------------------------------------------------------------------------------------------------------
    def _rows_date2int(self, rows):
        """
        Replaces start and end dates in a row set with their integer representation

        :param list[dict[str,T]] rows: The list of rows.

        :rtype: list[dict[str,T]]
        """
        ret = list()
        for row in rows:
            # Make a copy of the row such that self._rows is not affected by merge.
            tmp = copy.copy(row)

            # Determine the type of dates based on the first start date.
            if not self._date_type:
                self._date_type = self._get_date_type(tmp[self._key_start_date])

            # Convert dates to integers.
            tmp[self._key_start_date] = self._date2int(tmp[self._key_start_date])
            tmp[self._key_end_date] = self._date2int(tmp[self._key_end_date])
            ret.append(tmp)

        return ret

    # ------------------------------------------------------------------------------------------------------------------
    def _rows_int2date(self, rows):
        """
        Replaces start and end dates in the row set with their integer representation

        :param list[dict[str,T]] rows: The list of rows.
        """
        for row in rows:
            if self._date_type == 'str':
                row[self._key_start_date] = datetime.date.fromordinal(row[self._key_start_date]).isoformat()
                row[self._key_end_date] = datetime.date.fromordinal(row[self._key_end_date]).isoformat()
            elif self._date_type == 'date':
                row[self._key_start_date] = datetime.date.fromordinal(row[self._key_start_date])
                row[self._key_end_date] = datetime.date.fromordinal(row[self._key_end_date])
            else:
                raise ValueError('Unexpected date type {0!s}'.format(self._date_type))

    # ------------------------------------------------------------------------------------------------------------------
    def _rows_sort(self, rows):
        """
        Returns a list of rows sorted by start and end date.

        :param list[dict[str,T]] rows: The list of rows.

        :rtype: list[dict[str,T]]
        """
        return sorted(rows, key=lambda row: (row[self._key_start_date], row[self._key_end_date]))

    # ------------------------------------------------------------------------------------------------------------------
    @staticmethod
    def _get_date_type(date):
        """
        Returns the type of a date.

        :param str|datetime.date date: The date.

        :rtype: str
        """
        if isinstance(date, str):
            return 'str'

        if isinstance(date, datetime.date):
            return 'date'

        raise ValueError('Unexpected type {0!s}'.format(date.__class__))

    # ------------------------------------------------------------------------------------------------------------------
    def enumerate(self, name, start=1):
        """
        Enumerates all rows such that the natural key and the ordinal number are a unique key.

        :param str name: The key holding the ordinal number.
        :param start: The start of the ordinal numbers. Foreach natural key the first row has this ordinal number.
        """
        for natural_key, rows in self.rows.items():
            rows = self._rows_sort(rows)
            ordinal = start
            for row in rows:
                row[name] = ordinal
                ordinal += 1
            self.rows[natural_key] = rows

    # ------------------------------------------------------------------------------------------------------------------
    def get_rows(self):
        """
        Returns the rows of this Type2Helper.
        """
        ret = []
        for _, rows in self.rows.items():
            ret.extend(rows)

        return ret

    # ------------------------------------------------------------------------------------------------------------------
    def prepare_data(self, rows):
        """
        Sets and prepares the rows. The rows are stored in groups in a dictionary. A group is a list of rows with the
        same natural key. The key in the dictionary is a tuple with the values of the natural key.

        :param list[dict] rows: The rows
        """
        self.rows = dict()
        for row in rows:
            natural_key = self._get_natural_key(row)
            if natural_key not in self.rows:
                self.rows[natural_key] = list()
            self.rows[natural_key].append(row)

# ----------------------------------------------------------------------------------------------------------------------
<commit_msg>Bug fix.<commit_after>"""
ETLT

Copyright 2016 Set Based IT Consultancy

Licence MIT
"""
import copy
import datetime

class Type2Helper:
    """
    A helper class for reference data with date intervals.
    """

    # ------------------------------------------------------------------------------------------------------------------
    def __init__(self, key_start_date, key_end_date, natural_key):
        """
        Object constructor.

        :param str key_start_date: The key of the start date in the rows.
        :param str key_end_date: The key of the end date in the rows.
        :param list[str] natural_key: The keys of the columns that form the natural key.
        """
        self._natural_key = list(natural_key)
        """
        The keys of the columns that form the natural key.

        :type list[str]:
        """

        self._key_end_date = key_end_date
        """
        The key of the end date in the rows.

        :type str:
        """
        self._key_start_date = key_start_date
        """
        The key of the start date in the rows.

        :type str:
        """

        self.rows = dict()
        """
        The data set.

        :type dict:
        """

        self._date_type = ''
        """
        The type of the date fields.
        - date for datetime.date objects
        - str  for strings in ISO 8601 (YYYY-MM-DD) format.

        :type str:
        """

    # ------------------------------------------------------------------------------------------------------------------
    def _get_natural_key(self, row):
        """
        Returns the natural key in a row.

        :param dict row: The row.

        :rtype: tuple
        """
        ret = list()
        for key in self._natural_key:
            ret.append(row[key])

        return tuple(ret)

    # ------------------------------------------------------------------------------------------------------------------
    @staticmethod
    def _date2int(date):
        """
        Returns an integer representation of a date.

        :param str|datetime.date date: The date.

        :rtype: int
        """
        if isinstance(date, str):
            tmp = datetime.datetime.strptime(date, '%Y-%m-%d')
            return tmp.toordinal()

        if isinstance(date, datetime.date):
            return date.toordinal()

        if isinstance(date, int):
            return date

        raise ValueError('Unexpected type {0!s}'.format(date.__class__))

    # ------------------------------------------------------------------------------------------------------------------
    def _rows_date2int(self, rows):
        """
        Replaces start and end dates in a row set with their integer representation

        :param list[dict[str,T]] rows: The list of rows.

        :rtype: list[dict[str,T]]
        """
        ret = list()
        for row in rows:
            # Make a copy of the row such that self._rows is not affected by merge.
            tmp = copy.copy(row)

            # Determine the type of dates based on the first start date.
            if not self._date_type:
                self._date_type = self._get_date_type(tmp[self._key_start_date])

            # Convert dates to integers.
            tmp[self._key_start_date] = self._date2int(tmp[self._key_start_date])
            tmp[self._key_end_date] = self._date2int(tmp[self._key_end_date])
            ret.append(tmp)

        return ret

    # ------------------------------------------------------------------------------------------------------------------
    def _rows_int2date(self, rows):
        """
        Replaces start and end dates in the row set with their integer representation

        :param list[dict[str,T]] rows: The list of rows.
        """
        for row in rows:
            if self._date_type == 'str':
                row[self._key_start_date] = datetime.date.fromordinal(row[self._key_start_date]).isoformat()
                row[self._key_end_date] = datetime.date.fromordinal(row[self._key_end_date]).isoformat()
            elif self._date_type == 'date':
                row[self._key_start_date] = datetime.date.fromordinal(row[self._key_start_date])
                row[self._key_end_date] = datetime.date.fromordinal(row[self._key_end_date])
            else:
                raise ValueError('Unexpected date type {0!s}'.format(self._date_type))

    # ------------------------------------------------------------------------------------------------------------------
    def _rows_sort(self, rows):
        """
        Returns a list of rows sorted by start and end date.

        :param list[dict[str,T]] rows: The list of rows.

        :rtype: list[dict[str,T]]
        """
        return sorted(rows, key=lambda row: (row[self._key_start_date], row[self._key_end_date]))

    # ------------------------------------------------------------------------------------------------------------------
    @staticmethod
    def _get_date_type(date):
        """
        Returns the type of a date.

        :param str|datetime.date date: The date.

        :rtype: str
        """
        if isinstance(date, str):
            return 'str'

        if isinstance(date, datetime.date):
            return 'date'

        raise ValueError('Unexpected type {0!s}'.format(date.__class__))

    # ------------------------------------------------------------------------------------------------------------------
    def enumerate(self, name, start=1):
        """
        Enumerates all rows such that the natural key and the ordinal number are a unique key.

        :param str name: The key holding the ordinal number.
        :param start: The start of the ordinal numbers. Foreach natural key the first row has this ordinal number.
        """
        for natural_key, rows in self.rows.items():
            rows = self._rows_sort(rows)
            ordinal = start
            for row in rows:
                row[name] = ordinal
                ordinal += 1
            self.rows[natural_key] = rows

    # ------------------------------------------------------------------------------------------------------------------
    def get_rows(self):
        """
        Returns the rows of this Type2Helper.
        """
        ret = []
        for _, rows in self.rows.items():
            if self._date_type:
                self._rows_int2date(rows)
            ret.extend(rows)

        return ret

    # ------------------------------------------------------------------------------------------------------------------
    def prepare_data(self, rows):
        """
        Sets and prepares the rows. The rows are stored in groups in a dictionary. A group is a list of rows with the
        same natural key. The key in the dictionary is a tuple with the values of the natural key.

        :param list[dict] rows: The rows
        """
        self.rows = dict()
        for row in rows:
            natural_key = self._get_natural_key(row)
            if natural_key not in self.rows:
                self.rows[natural_key] = list()
            self.rows[natural_key].append(row)

# ----------------------------------------------------------------------------------------------------------------------
<|endoftext|>


<commit_before># coding: utf-8

import logging

from authomatic.extras.flask import FlaskAuthomatic
from authomatic.providers import oauth2
from datetime import datetime, timedelta
from flask import Flask, make_response
from flask import session, request, url_for
from flask import render_template, redirect, jsonify
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import gen_salt
from flask_oauthlib.provider import OAuth2Provider

logger = logging.getLogger('authomatic.core')
logger.addHandler(logging.StreamHandler())

app = Flask(__name__, template_folder='templates')
app.config.from_pyfile('application.cfg', silent=False)

db = SQLAlchemy(app)
oauth = OAuth2Provider(app)

fa = FlaskAuthomatic(
    config={
        'fb': {
           'class_': oauth2.Facebook,
           'consumer_key': app.config['CONSUMER_KEY'],
           'consumer_secret': app.config['CONSUMER_SECRET'],
           'scope': ['user_about_me', 'email'],
        },
    },
    secret=app.config['SECRET_KEY'],
    debug=True,
)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(40), unique=True)

class Client(db.Model):
    client_id = db.Column(db.String(40), primary_key=True)
    client_secret = db.Column(db.String(55), nullable=False)

    user_id = db.Column(db.ForeignKey('user.id'))
    user = db.relationship('User')

    _redirect_uris = db.Column(db.Text)
    _default_scopes = db.Column(db.Text)

    @property
    def client_type(self):
        return 'public'

    @property
    def redirect_uris(self):
        if self._redirect_uris:
            return self._redirect_uris.split()
        return []

    @property
    def default_redirect_uri(self):
        return self.redirect_uris[0]

    @property
    def default_scopes(self):
        if self._default_scopes:
            return self._default_scopes.split()
        return []

    def validate_redirect_uri(self, redirect_uri):
        # Chop query string and confirm it's in the list
        redirect_uri = redirect_uri.split('?')[0]
        return redirect_uri in self.redirect_uris

class Grant(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    user_id = db.Column(
        db.Integer, db.ForeignKey('user.id', ondelete='CASCADE')
    )
    user = db.relationship('User')

    client_id = db.Column(
        db.String(40), db.ForeignKey('client.client_id'),
        nullable=False,
    )
    client = db.relationship('Client')

    code = db.Column(db.String(255), index=True, nullable=False)

    redirect_uri = db.Column(db.String(255))
    expires = db.Column(db.DateTime)

    _scopes = db.Column(db.Text)

    def delete(self):
        db.session.delete(self)
        db.session.commit()
        return self

    @property
    def scopes(self):
        if self._scopes:
            return self._scopes.split()
        return []

class Token(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    client_id = db.Column(
        db.String(40), db.ForeignKey('client.client_id'),
        nullable=False,
    )
    client = db.relationship('Client')

    user_id = db.Column(
        db.Integer, db.ForeignKey('user.id')
    )
    user = db.relationship('User')

    # currently only bearer is supported
    token_type = db.Column(db.String(40))

    access_token = db.Column(db.String(255), unique=True)
    refresh_token = db.Column(db.String(255), unique=True)
    expires = db.Column(db.DateTime)
    _scopes = db.Column(db.Text)

    @property
    def scopes(self):
        if self._scopes:
            return self._scopes.split()
        return []

class Assessment(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(
        db.Integer, db.ForeignKey('user.id')
    )
    user = db.relationship('User')
    assessment_type = db.Column(db.String(40))
    taken = db.Column(db.DateTime)

def current_user():
    if 'id' in session:
        uid = session['id']
        return User.query.get(uid)
    return None

@app.route('/terms-of-use')
def termsofuse():
    return render_template('termsofuse.html')

#@app.route('/', methods=('GET', 'POST'))
#def home():
#    user = current_user()
#    return render_template('home.html', user=user, session=session,
#            cookies=request.cookies)

@app.route('/')
def index():
    user = current_user()
    if user:
        return render_template('portal.html', PORTAL=app.config['PORTAL'],
                user=user)
    return render_template('index.html', PORTAL=app.config['PORTAL'])

@app.route('/client', methods=('GET', 'POST'))
def client():
    user = current_user()
    if not user:
        return redirect('/')
    if request.method == 'GET':
        return render_template('register_client.html')
    redirect_uri = request.form.get('redirect_uri', None)
    item = Client(
        client_id=gen_salt(40),
        client_secret=gen_salt(50),
        _redirect_uris=redirect_uri,
        _default_scopes='email',
        user_id=user.id,
    )
    db.session.add(item)
    db.session.commit()
    return jsonify(
        client_id=item.client_id,
        client_secret=item.client_secret,
        redirect_uris=item._redirect_uris
    )

@oauth.clientgetter
def load_client(client_id):
    return Client.query.filter_by(client_id=client_id).first()

@oauth.grantgetter
def load_grant(client_id, code):
    return Grant.query.filter_by(client_id=client_id, code=code).first()

@oauth.grantsetter
def save_grant(client_id, code, request, *args, **kwargs):
    # decide the expires time yourself
    expires = datetime.utcnow() + timedelta(seconds=100)
    grant = Grant(
        client_id=client_id,
        code=code['code'],
        redirect_uri=request.redirect_uri,
        _scopes=' '.join(request.scopes),
        user=current_user(),
        expires=expires
    )
    db.session.add(grant)
    db.session.commit()
    return grant

@oauth.tokengetter
def load_token(access_token=None, refresh_token=None):
    if access_token:
        return Token.query.filter_by(access_token=access_token).first()
    elif refresh_token:
        return Token.query.filter_by(refresh_token=refresh_token).first()

@oauth.tokensetter
def save_token(token, request, *args, **kwargs):
    toks = Token.query.filter_by(
        client_id=request.client.client_id,
        user_id=request.user.id
    )
    # make sure that every client has only one token connected to a user
    for t in toks:
        db.session.delete(t)

    expires_in = token.pop('expires_in')
    expires = datetime.utcnow() + timedelta(seconds=expires_in)

    tok = Token(
        access_token=token['access_token'],
        refresh_token=token['refresh_token'],
        token_type=token['token_type'],
        _scopes=token['scope'],
        expires=expires,
        client_id=request.client.client_id,
        user_id=request.user.id,
    )
    db.session.add(tok)
    db.session.commit()
    return tok

@app.route('/oauth/token', methods=['GET', 'POST'])
@oauth.token_handler
def access_token():
    return None

@app.route('/oauth/authorize', methods=['GET', 'POST'])
@oauth.authorize_handler
def authorize(*args, **kwargs):
    user = current_user()
    if not user:
        return redirect('/')
    # Skip confirmation - return true as if user agreed to
    # let portal give API access to intervetion.
    return True

@app.route('/api/me')
@oauth.require_oauth()
def me():
    user = request.oauth.user
    return jsonify(username=user.username)

@app.route('/api/demographics')
@oauth.require_oauth()
def demographics():
    demographics_data = {
        "id": 854387,
        "name": {
            "given": "Patrick",
            "family": "Testa"
        },
        "birthDate": "1970-06-09",
        "communication": "en-US",
        "telecom": [
            {
                "system": "email",
                "value": "helloworld@movember.com"
            },
            {
                "system": "phone",
                "value": "(123) 456-7890"
            },

        ],
        "status": "registered",
    }
    return jsonify(demographics_data)

@app.route('/api/clinical')
@oauth.require_oauth()
def clinical():
    clinical_data = {
        "TNM-Condition-stage": {
            "summary": "T1 N0 M0"
        },
        "Gleason-score": "2"
    }
    return jsonify(clinical_data)

@app.route('/api/assessments')
@oauth.require_oauth()
def assessments():
    addone = Assessment(
        user_id=request.oauth.user.id,
        assessment_type='test type',
        taken=datetime.now())
    db.session.add(addone)
    db.session.commit()
    aments = Assessment.query.filter_by(
        user_id=request.oauth.user.id
    )
    return jsonify(count=aments.count())

@app.route('/api/portal-wrapper-html')
def portal_wrapper_html():
    html = render_template(
        'portal_wrapper.html',
        PORTAL=app.config['PORTAL'],
        logo_truenth=url_for(
            'static',
            filename='img/logo_truenth.png',
        ),
        logo_movember=url_for(
            'static',
            filename='img/logo_movember.png',
        ),
    )
    resp = make_response(html)
    resp.headers.add('Access-Control-Allow-Origin', '*')
    resp.headers.add('Access-Control-Allow-Headers', 'X-Requested-With')
    return resp

@app.route('/login')
@fa.login('fb')
def login():
    user = current_user()
    if user:
        return redirect('/')
    if fa.result:
        if fa.result.error:
            return fa.result.error.message
        elif fa.result.user:
            if not (fa.result.user.name and fa.result.user.id):
                fa.result.user.update()
            # Success - add or pull this user to/from portal store
            username = fa.result.user.name
            user = User.query.filter_by(username=username).first()
            if not user:
                user = User(username=username)
                db.session.add(user)
                db.session.commit()
            user_id = user.id
            session['id'] = user_id
            session['fa_user_id'] = fa.result.user.id
            return redirect('/')
    else:
        return fa.response

@app.route('/logout')
def logout():
    session.clear()
    return redirect('/')

if __name__ == '__main__':
    db.create_all()
    app.run(host='0.0.0.0')
<commit_msg>Implement facebook logout.<commit_after># coding: utf-8

import logging
import requests

from authomatic.extras.flask import FlaskAuthomatic
from authomatic.providers import oauth2
from datetime import datetime, timedelta
from flask import Flask, make_response
from flask import session, request, url_for
from flask import render_template, redirect, jsonify
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import gen_salt
from flask_oauthlib.provider import OAuth2Provider

logger = logging.getLogger('authomatic.core')
logger.addHandler(logging.StreamHandler())

app = Flask(__name__, template_folder='templates')
app.config.from_pyfile('application.cfg', silent=False)

db = SQLAlchemy(app)
oauth = OAuth2Provider(app)

fa = FlaskAuthomatic(
    config={
        'fb': {
           'class_': oauth2.Facebook,
           'consumer_key': app.config['CONSUMER_KEY'],
           'consumer_secret': app.config['CONSUMER_SECRET'],
           'scope': ['user_about_me', 'email'],
        },
    },
    secret=app.config['SECRET_KEY'],
    debug=True,
)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(40), unique=True)

class Client(db.Model):
    client_id = db.Column(db.String(40), primary_key=True)
    client_secret = db.Column(db.String(55), nullable=False)

    user_id = db.Column(db.ForeignKey('user.id'))
    user = db.relationship('User')

    _redirect_uris = db.Column(db.Text)
    _default_scopes = db.Column(db.Text)

    @property
    def client_type(self):
        return 'public'

    @property
    def redirect_uris(self):
        if self._redirect_uris:
            return self._redirect_uris.split()
        return []

    @property
    def default_redirect_uri(self):
        return self.redirect_uris[0]

    @property
    def default_scopes(self):
        if self._default_scopes:
            return self._default_scopes.split()
        return []

    def validate_redirect_uri(self, redirect_uri):
        # Chop query string and confirm it's in the list
        redirect_uri = redirect_uri.split('?')[0]
        return redirect_uri in self.redirect_uris

class Grant(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    user_id = db.Column(
        db.Integer, db.ForeignKey('user.id', ondelete='CASCADE')
    )
    user = db.relationship('User')

    client_id = db.Column(
        db.String(40), db.ForeignKey('client.client_id'),
        nullable=False,
    )
    client = db.relationship('Client')

    code = db.Column(db.String(255), index=True, nullable=False)

    redirect_uri = db.Column(db.String(255))
    expires = db.Column(db.DateTime)

    _scopes = db.Column(db.Text)

    def delete(self):
        db.session.delete(self)
        db.session.commit()
        return self

    @property
    def scopes(self):
        if self._scopes:
            return self._scopes.split()
        return []

class Token(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    client_id = db.Column(
        db.String(40), db.ForeignKey('client.client_id'),
        nullable=False,
    )
    client = db.relationship('Client')

    user_id = db.Column(
        db.Integer, db.ForeignKey('user.id')
    )
    user = db.relationship('User')

    # currently only bearer is supported
    token_type = db.Column(db.String(40))

    access_token = db.Column(db.String(255), unique=True)
    refresh_token = db.Column(db.String(255), unique=True)
    expires = db.Column(db.DateTime)
    _scopes = db.Column(db.Text)

    @property
    def scopes(self):
        if self._scopes:
            return self._scopes.split()
        return []

class Assessment(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(
        db.Integer, db.ForeignKey('user.id')
    )
    user = db.relationship('User')
    assessment_type = db.Column(db.String(40))
    taken = db.Column(db.DateTime)

def current_user():
    if 'id' in session:
        uid = session['id']
        return User.query.get(uid)
    return None

@app.route('/terms-of-use')
def termsofuse():
    return render_template('termsofuse.html')

@app.route('/')
def index():
    user = current_user()
    if user:
        return render_template('portal.html', PORTAL=app.config['PORTAL'],
                user=user)
    return render_template('index.html', PORTAL=app.config['PORTAL'])

@app.route('/client', methods=('GET', 'POST'))
def client():
    user = current_user()
    if not user:
        return redirect('/')
    if request.method == 'GET':
        return render_template('register_client.html')
    redirect_uri = request.form.get('redirect_uri', None)
    item = Client(
        client_id=gen_salt(40),
        client_secret=gen_salt(50),
        _redirect_uris=redirect_uri,
        _default_scopes='email',
        user_id=user.id,
    )
    db.session.add(item)
    db.session.commit()
    return jsonify(
        client_id=item.client_id,
        client_secret=item.client_secret,
        redirect_uris=item._redirect_uris
    )

@oauth.clientgetter
def load_client(client_id):
    return Client.query.filter_by(client_id=client_id).first()

@oauth.grantgetter
def load_grant(client_id, code):
    return Grant.query.filter_by(client_id=client_id, code=code).first()

@oauth.grantsetter
def save_grant(client_id, code, request, *args, **kwargs):
    # decide the expires time yourself
    expires = datetime.utcnow() + timedelta(seconds=100)
    grant = Grant(
        client_id=client_id,
        code=code['code'],
        redirect_uri=request.redirect_uri,
        _scopes=' '.join(request.scopes),
        user=current_user(),
        expires=expires
    )
    db.session.add(grant)
    db.session.commit()
    return grant

@oauth.tokengetter
def load_token(access_token=None, refresh_token=None):
    if access_token:
        return Token.query.filter_by(access_token=access_token).first()
    elif refresh_token:
        return Token.query.filter_by(refresh_token=refresh_token).first()

@oauth.tokensetter
def save_token(token, request, *args, **kwargs):
    toks = Token.query.filter_by(
        client_id=request.client.client_id,
        user_id=request.user.id
    )
    # make sure that every client has only one token connected to a user
    for t in toks:
        db.session.delete(t)

    expires_in = token.pop('expires_in')
    expires = datetime.utcnow() + timedelta(seconds=expires_in)

    tok = Token(
        access_token=token['access_token'],
        refresh_token=token['refresh_token'],
        token_type=token['token_type'],
        _scopes=token['scope'],
        expires=expires,
        client_id=request.client.client_id,
        user_id=request.user.id,
    )
    db.session.add(tok)
    db.session.commit()
    return tok

@app.route('/oauth/token', methods=['GET', 'POST'])
@oauth.token_handler
def access_token():
    return None

@app.route('/oauth/authorize', methods=['GET', 'POST'])
@oauth.authorize_handler
def authorize(*args, **kwargs):
    user = current_user()
    if not user:
        return redirect('/')
    # Skip confirmation - return true as if user agreed to
    # let portal give API access to intervetion.
    return True

@app.route('/api/me')
@oauth.require_oauth()
def me():
    user = request.oauth.user
    return jsonify(username=user.username)

@app.route('/api/demographics')
@oauth.require_oauth()
def demographics():
    demographics_data = {
        "id": 854387,
        "name": {
            "given": "Patrick",
            "family": "Testa"
        },
        "birthDate": "1970-06-09",
        "communication": "en-US",
        "telecom": [
            {
                "system": "email",
                "value": "helloworld@movember.com"
            },
            {
                "system": "phone",
                "value": "(123) 456-7890"
            },

        ],
        "status": "registered",
    }
    return jsonify(demographics_data)

@app.route('/api/clinical')
@oauth.require_oauth()
def clinical():
    clinical_data = {
        "TNM-Condition-stage": {
            "summary": "T1 N0 M0"
        },
        "Gleason-score": "2"
    }
    return jsonify(clinical_data)

@app.route('/api/assessments')
@oauth.require_oauth()
def assessments():
    addone = Assessment(
        user_id=request.oauth.user.id,
        assessment_type='test type',
        taken=datetime.now())
    db.session.add(addone)
    db.session.commit()
    aments = Assessment.query.filter_by(
        user_id=request.oauth.user.id
    )
    return jsonify(count=aments.count())

@app.route('/api/portal-wrapper-html')
def portal_wrapper_html():
    html = render_template(
        'portal_wrapper.html',
        PORTAL=app.config['PORTAL'],
        logo_truenth=url_for(
            'static',
            filename='img/logo_truenth.png',
        ),
        logo_movember=url_for(
            'static',
            filename='img/logo_movember.png',
        ),
    )
    resp = make_response(html)
    resp.headers.add('Access-Control-Allow-Origin', '*')
    resp.headers.add('Access-Control-Allow-Headers', 'X-Requested-With')
    return resp

@app.route('/login')
@fa.login('fb')
def login():
    user = current_user()
    if user:
        return redirect('/')
    if fa.result:
        if fa.result.error:
            return fa.result.error.message
        elif fa.result.user:
            if not (fa.result.user.name and fa.result.user.id):
                fa.result.user.update()
            # Success - add or pull this user to/from portal store
            username = fa.result.user.name
            user = User.query.filter_by(username=username).first()
            if not user:
                user = User(username=username)
                db.session.add(user)
                db.session.commit()
            user_id = user.id
            session['id'] = user_id
            session['fa_user_id'] = fa.result.user.id
            session['fa_token'] = fa.result.provider.credentials.token
            return redirect('/')
    else:
        return fa.response

@app.route('/logout')
def logout():
    headers = {'Authorization':
            'Bearer {0}'.format(session['fa_token'])}
    url = "https://graph.facebook.com/{0}/permissions".\
        format(session['fa_user_id'])
    result = requests.delete(url, headers=headers)
    session.clear()
    return redirect('/')

if __name__ == '__main__':
    db.create_all()
    app.run(host='0.0.0.0')
<|endoftext|>


<commit_before>#!/usr/bin/env python
import os
import time
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.request, urllib.parse
import random
import json

class RequestHandler(BaseHTTPRequestHandler):
    def username_in_use(self, username):
        data = self.get_data()
        names = [x['username'] for x in data.values()]
        return username in names

    def get_data_path(self):
        if not 'OPENSHIFT_DATA_DIR' in os.environ:
            return '../data/data.json'
        else:
            return os.path.join(os.environ['OPENSHIFT_DATA_DIR'], 'data.json')

    def get_data(self):
        if not os.path.isfile(self.get_data_path()):
            with open(self.get_data_path(), 'w') as fh:
                fh.write("{}")
        data = json.load(open(self.get_data_path(), 'r'))
        print(data)
        return data

    def write_data(self, data):
        json.dump(data, open(self.get_data_path(), 'w'), sort_keys=True,
                    indent=4, separators=(',', ': '))

    def get_own_api_root(self):
        if 'OPENSHIFT_DATA_DIR' in os.environ:
            return 'https://pythonbackend-stepupforpebble.rhcloud.com/'
        else:
            return 'http://localhost:8080/'

    def username_to_uid(self, data, username):
        for key, item in data.items():
            if 'username' in item and item['username'] == username:
                return key
        return False

    def uid_to_username(self, data, uid):
        if uid in data:
            return data[uid]['username']
        return False

    def respond(self, code, string):
        self.send_response(code)
        self.end_headers()
        if code == 200:
            self.wfile.write(bytes(string, 'utf-8'))
        else:
            self.wfile.write(bytes(str(code) + ' ' + string, 'utf-8'))

    def pin(self, data, uid, pinData, pinId):
        if 'tltoken' in data[uid]:
            url = 'https://timeline-api.getpebble.com/v1/user/pins/' + pinId
            req = urllib.request.Request(
                            url,
                            data = bytes(json.dumps(pinData), 'utf-8'),
                            method = 'PUT',
                            headers = {
                                'Content-Type': 'application/json',
                                'X-User-Token': data[uid]['tltoken']
                            })
            print('URL: -----> -----> ', req.full_url)
            print('DATA: -----> -----> ', req.data)
            print('METHOD: -----> -----> ', req.get_method())
            print('HEADERS: -----> -----> ', req.headers)
            with urllib.request.urlopen(req) as response:
                data = response.read()
                print(data)
        else:
            print('Tltoken for ' + uid + ' is missing. Not pinning.')

    def set_username(self, uid, username):
        try:
            data = self.get_data()
            for key, item in data.items():
                if key != uid:
                    if item['username'] == username.lower().strip():
                        return (400, 'Username taken')
            for key, item in data.items():
                if key == uid:
                    item['username'] = username.lower().strip()
                    self.write_data(data)
                    return (200, 'OK')
            data[uid] = {'username': username.lower().strip()}
            self.write_data(data)
            return (200, 'OK (created)')
        except ValueError as e:
            print(e)
        return (400, 'Misc failure')

    def set_timeline_token(self, uid, tltoken):
        data = self.get_data()
        for key, item in data.items():
            if key == uid:
                item['tltoken'] = tltoken
                self.write_data(data)
                return (200, 'OK')
        return (400, 'User doesn\'t exist')

    def add_data_point(self, uid, timePeriod, steps):
        try:
            steps = int(steps)
        except ValueError:
            return (400, 'Malformed Steps Data')
        data = self.get_data()
        if not uid in data:
            data[uid] = {}
        if not 'history' in data[uid]:
            data[uid]['history'] = {}
        data[uid]['history'][timePeriod] = steps
        data[uid]['history'] = pruneHistory(data[uid]['history'])
        self.write_data(data)
        return (200, 'OK')

    def get_friends(self, uid):
        data = self.get_data()
        if not uid in data:
            data[uid] = {}
        if not 'friends' in data[uid]:
            data[uid]['friends'] = []
        friends = data[uid]['friends']
        friends = [self.uid_to_username(data, friend) for friend in friends]
        return (200, json.dumps(friends))
        self.write_data(data)

    def add_friend(self, uid, friendUsername):
        data = self.get_data()
        if not uid in data:
            return (400, 'User doesn\'t exist');
        if not 'friends' in data[uid]:
            data[uid]['friends'] = []
        if len(data[uid]['friends']) >= 20:
            return (409, 'You can\'t add that many friends.')
        if self.uid_to_username(data, uid) == friendUsername:
            return (409, 'You can\'t add yourself as a friend.')
        friendUUID = self.username_to_uid(data, friendUsername)
        if friendUUID is not False:
            data[uid]['friends'] += [self.username_to_uid(data, friendUsername)]
            data[uid]['friends'] = list(set(data[uid]['friends']))
            self.write_data(data)
            return (200, json.dumps([self.uid_to_username(data, x) for x in
                                     data[uid]['friends']]))
        else:
            return (400, 'User doesn\'t exist.')

    def send_friend_request(self, uid, friendUsername):
        # TODO dont allow sending friend reqs to people you've already friended.
        data = self.get_data()
        if not uid in data:
            return (400, 'Your user doesn\'t exist');
        friendUUID = self.username_to_uid(data, friendUsername)
        if friendUUID is not False and\
           friendUUID in data:
            requestorUsername = self.uid_to_username(data, uid)
            if not 'friendReqs' in data[friendUUID]:
                data[friendUUID]['friendReqs'] = []
            if not 'friendReqs' in data[uid]:
                data[uid]['friendReqs'] = []
            if len(data[friendUUID]['friendReqs']) >= 20:
                return (409, 'That person has maxed out their friends!')
            if len(data[uid]['friendReqs']) >= 20:
                return (409, 'You have maxed out their friends!')
            if uid == friendUUID:
                return (409, 'You can\'t add yourself as a friend.')
            if friendUUID in data[uid]['friendReqs']:
                if not 'friends' in data[friendUUID]:
                    data[friendUUID]['friends'] = []
                if not 'friends' in data[uid]:
                    data[uid]['friends'] = []

                # Yay! Friend request acception time!
                print('mutual acception', uid, friendUUID)
                try:
                    data[friendUUID]['friends'] += [uid]
                    data[uid]['friends'] += [friendUUID]
                    data[friendUUID]['friends'] = list(set(data[friendUUID]['friends']))
                    data[uid]['friends'] = list(set(data[uid]['friends']))
                    if uid in data[friendUUID]['friendReqs']:
                        data[friendUUID]['friendReqs'].remove(uid)
                    if friendUUID in data[uid]['friendReqs']:
                        data[uid]['friendReqs'].remove(friendUUID)
                    for _uuid, _username in [(uid, friendUsername),
                                             (friendUUID, requestorUsername)]:
                        pinId = 'friend-request-' + str(random.randint(10**8, 10**9))
                        self.pin(data, _uuid, {
                            'time': time.strftime("%Y-%m-%dT%H:%M:%S"),
                            'id': pinId,
                            'layout': {
                                'type': 'genericPin',
                                'title': 'New Friend!',
                                'subtitle': 'Step Up!',
                                'body': _username + ' is now your friend on Step Up!'
                            },
                            'createNotification': {
                                'layout': {
                                    'type': 'genericNotification',
                                    'title': 'New Friend!',
                                    'body': 'You and ' + _username + ' are now friends on Step Up!'
                                }
                            }
                        }, pinId)
                except ValueError as e:
                    print(e)
                self.write_data(data)
                return (200, 'OK')
            else:
                # Let's go make some friends!
                data[friendUUID]['friendReqs'] += [uid]
                data[friendUUID]['friendReqs'] = list(set(data[friendUUID]['friendReqs']))
                self.write_data(data)
                try:
                    pinId = 'friend-request-' + str(random.randint(10**8, 10**9))
                    self.pin(data, friendUUID, {
                        'time': time.strftime("%Y-%m-%dT%H:%M:%S"),
                        'id': pinId,
                        'layout': {
                            'type': 'genericPin',
                            'title': 'Friend Request!',
                            'subtitle': 'Step Up!',
                            'body': requestorUsername + ' wants to be your friend on Step Up!'
                        },
                        'createNotification': {
                            'layout': {
                                'type': 'genericNotification',
                                'title': 'Friend Request!',
                                'body': requestorUsername +
                                    ' wants to be your friend on Step Up!\n' +
                                    'Select "More" from actions to accept.'
                            }
                        },
                        'actions': [
                            {
                                'type': 'http',
                                'method': 'GET',
                                'title': 'Accept',
                                'url': self.get_own_api_root() +
                                       'send_friend_request?uid=' + friendUUID +
                                       '&addusername=' + requestorUsername
                            }
                        ]
                    }, pinId)
                except urllib.error.HTTPError as e:
                    return (200, 'pin sending failure: ' + e.read().decode('utf-8'))
                return (200, 'OK')
        else:
            return (400, 'Friending user doesn\'t exist.')

    def delete_friend(self, uid, friendUsername):
        data = self.get_data()
        if not uid in data:
            data[uid] = {}
        if not 'friends' in data[uid]:
            data[uid]['friends'] = []
        friendUUID = self.username_to_uid(data, friendUsername)
        requestorUsername = self.uid_to_username(data, uid)

        data[uid]['friends'] = list(set(data[uid]['friends']))
        if friendUUID in data[uid]['friends']:
            data[uid]['friends'].remove(friendUUID)

        if not friendUUID is False:
            data[friendUUID]['friends'] = list(set(data[friendUUID]['friends']))
            if uid in data[friendUUID]['friends']:
                data[friendUUID]['friends'].remove(uid)

            self.write_data(data)
            return (200, json.dumps(data[uid]['friends']))
        else:
            return (400, 'User doesn\'t exist.')

    def dump_data(self):
        data = self.get_data()
        out = '<!DOCTYPE html>'
        for key, value in sorted(data.items(), key=lambda x: x[0]):
            out += '' + key + '' +\
                   '
'
            for propKey, propVal in sorted(value.items(), key=lambda x: x[0]):
                out += '' + propKey + ': ' +\
                       '' + json.dumps(propVal) + '
'
            out += '
'
        out += ''
        return (200, out)

    def end_headers(self):
        self.send_header('Access-Control-Allow-Origin', '*')
        BaseHTTPRequestHandler.end_headers(self)

    def do_GET(self):
        urldata = urllib.parse.urlparse(self.path)
        qdata = urllib.parse.parse_qs(urldata.query)
        print(qdata)
        try:
            self.path.index('/dump')
            try:
                # NB this removes it in prod
                assert not 'OPENSHIFT_PYTHON_IP' in os.environ
                info = self.dump_data()
                print(info)
                self.respond(info[0], info[1])
                return
            except AssertionError:
                pass
        except ValueError:
            pass
        try:
            self.path.index('/username_in_use')
            try:
                assert 'username' in qdata
                info = self.username_in_use(qdata['username'][0])
                self.respond(200, json.dumps(str(info)))
            except AssertionError:
                self.respond(400, 'Malformed Request')
                return
        except ValueError:
            pass
        try:
            self.path.index('/add_data')
            try:
                assert 'uid' in qdata and\
                       'timeperiod' in qdata and\
                       'steps' in qdata
                info = self.add_data_point(qdata['uid'][0],
                                           qdata['timeperiod'][0],
                                           qdata['steps'][0])
                if (len(info) == 2):
                    self.respond(info[0], info[1])
            except AssertionError:
                self.respond(400, 'Malformed Request')
                return
        except ValueError:
            pass
        try:
            self.path.index('/send_friend_request')
            try:
                assert 'uid' in qdata and\
                       'addusername' in qdata
                info = self.send_friend_request(qdata['uid'][0],
                                                qdata['addusername'][0])
                if (len(info) == 2):
                    self.respond(info[0], info[1])
                    return
            except AssertionError:
                self.respond(400, 'Malformed Request')
                return
        except ValueError:
            pass
        try:
            self.path.index('/get_friends')
            try:
                assert 'uid' in qdata
                info = self.get_friends(qdata['uid'][0])
                self.respond(info[0], info[1])
            except AssertionError:
                self.respond(400, 'Malformed request')
            return
        except ValueError:
            pass
        try:
            self.path.index('/delete_friend')
            try:
                assert 'uid' in qdata and\
                       'deleteusername' in qdata
                info = self.delete_friend(qdata['uid'][0],
                                          qdata['deleteusername'][0])
                self.respond(info[0], info[1])
            except AssertionError:
                self.respond(400, 'Malformed request')
            return
        except ValueError:
            pass
        try:
            self.path.index('/get_username')
            try:
                assert 'uid' in qdata
                print(self.path)
                username = self.uid_to_username(self.get_data(), qdata['uid'][0])
                if username is not False:
                    self.respond(200, json.dumps(username))
                else:
                    self.respond(404, 'User not registered')
                return
            except AssertionError:
                self.respond(400, 'Malformed request')
                return
        except ValueError:
            pass
        try:
            self.path.index('/set_username')
            try:
                assert 'uid' in qdata and\
                       'username' in qdata
                print(self.path)
                info = self.set_username(qdata['uid'][0], qdata['username'][0])
                self.respond(info[0], info[1])
                return
            except AssertionError:
                self.respond(400, 'Malformed request')
                return
        except ValueError:
            pass
        try:
            self.path.index('/set_timeline_token')
            try:
                assert 'uid' in qdata and\
                       'tltoken' in qdata
                print(self.path)
                info = self.set_timeline_token(qdata['uid'][0], qdata['tltoken'][0])
                self.respond(info[0], info[1])
                return
            except AssertionError:
                self.respond(400, 'Malformed request')
                return
        except ValueError:
            pass
        self.respond(400, 'Method missing')

if __name__ == '__main__':
    if 'OPENSHIFT_PYTHON_IP' in os.environ:
        server_address = (os.environ['OPENSHIFT_PYTHON_IP'],
                          int(os.environ['OPENSHIFT_PYTHON_PORT']))
    else:
        server_address = ('', 8080)
    httpd = HTTPServer(server_address, RequestHandler)
    httpd.serve_forever()
<commit_msg> :raising_hand: fix another possible issue with friend removal<commit_after>#!/usr/bin/env python
import os
import time
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.request, urllib.parse
import random
import json

class RequestHandler(BaseHTTPRequestHandler):
    def username_in_use(self, username):
        data = self.get_data()
        names = [x['username'] for x in data.values()]
        return username in names

    def get_data_path(self):
        if not 'OPENSHIFT_DATA_DIR' in os.environ:
            return '../data/data.json'
        else:
            return os.path.join(os.environ['OPENSHIFT_DATA_DIR'], 'data.json')

    def get_data(self):
        if not os.path.isfile(self.get_data_path()):
            with open(self.get_data_path(), 'w') as fh:
                fh.write("{}")
        data = json.load(open(self.get_data_path(), 'r'))
        print(data)
        return data

    def write_data(self, data):
        json.dump(data, open(self.get_data_path(), 'w'), sort_keys=True,
                    indent=4, separators=(',', ': '))

    def get_own_api_root(self):
        if 'OPENSHIFT_DATA_DIR' in os.environ:
            return 'https://pythonbackend-stepupforpebble.rhcloud.com/'
        else:
            return 'http://localhost:8080/'

    def username_to_uid(self, data, username):
        for key, item in data.items():
            if 'username' in item and item['username'] == username:
                return key
        return False

    def uid_to_username(self, data, uid):
        if uid in data:
            return data[uid]['username']
        return False

    def respond(self, code, string):
        self.send_response(code)
        self.end_headers()
        if code == 200:
            self.wfile.write(bytes(string, 'utf-8'))
        else:
            self.wfile.write(bytes(str(code) + ' ' + string, 'utf-8'))

    def pin(self, data, uid, pinData, pinId):
        if 'tltoken' in data[uid]:
            url = 'https://timeline-api.getpebble.com/v1/user/pins/' + pinId
            req = urllib.request.Request(
                            url,
                            data = bytes(json.dumps(pinData), 'utf-8'),
                            method = 'PUT',
                            headers = {
                                'Content-Type': 'application/json',
                                'X-User-Token': data[uid]['tltoken']
                            })
            print('URL: -----> -----> ', req.full_url)
            print('DATA: -----> -----> ', req.data)
            print('METHOD: -----> -----> ', req.get_method())
            print('HEADERS: -----> -----> ', req.headers)
            with urllib.request.urlopen(req) as response:
                data = response.read()
                print(data)
        else:
            print('Tltoken for ' + uid + ' is missing. Not pinning.')

    def set_username(self, uid, username):
        try:
            data = self.get_data()
            for key, item in data.items():
                if key != uid:
                    if item['username'] == username.lower().strip():
                        return (400, 'Username taken')
            for key, item in data.items():
                if key == uid:
                    item['username'] = username.lower().strip()
                    self.write_data(data)
                    return (200, 'OK')
            data[uid] = {'username': username.lower().strip()}
            self.write_data(data)
            return (200, 'OK (created)')
        except ValueError as e:
            print(e)
        return (400, 'Misc failure')

    def set_timeline_token(self, uid, tltoken):
        data = self.get_data()
        for key, item in data.items():
            if key == uid:
                item['tltoken'] = tltoken
                self.write_data(data)
                return (200, 'OK')
        return (400, 'User doesn\'t exist')

    def add_data_point(self, uid, timePeriod, steps):
        try:
            steps = int(steps)
        except ValueError:
            return (400, 'Malformed Steps Data')
        data = self.get_data()
        if not uid in data:
            data[uid] = {}
        if not 'history' in data[uid]:
            data[uid]['history'] = {}
        data[uid]['history'][timePeriod] = steps
        data[uid]['history'] = pruneHistory(data[uid]['history'])
        self.write_data(data)
        return (200, 'OK')

    def get_friends(self, uid):
        data = self.get_data()
        if not uid in data:
            data[uid] = {}
        if not 'friends' in data[uid]:
            data[uid]['friends'] = []
        friends = data[uid]['friends']
        friends = [self.uid_to_username(data, friend) for friend in friends]
        return (200, json.dumps(friends))
        self.write_data(data)

    def add_friend(self, uid, friendUsername):
        data = self.get_data()
        if not uid in data:
            return (400, 'User doesn\'t exist');
        if not 'friends' in data[uid]:
            data[uid]['friends'] = []
        if len(data[uid]['friends']) >= 20:
            return (409, 'You can\'t add that many friends.')
        if self.uid_to_username(data, uid) == friendUsername:
            return (409, 'You can\'t add yourself as a friend.')
        friendUUID = self.username_to_uid(data, friendUsername)
        if friendUUID is not False:
            data[uid]['friends'] += [self.username_to_uid(data, friendUsername)]
            data[uid]['friends'] = list(set(data[uid]['friends']))
            self.write_data(data)
            return (200, json.dumps([self.uid_to_username(data, x) for x in
                                     data[uid]['friends']]))
        else:
            return (400, 'User doesn\'t exist.')

    def send_friend_request(self, uid, friendUsername):
        # TODO dont allow sending friend reqs to people you've already friended.
        data = self.get_data()
        if not uid in data:
            return (400, 'Your user doesn\'t exist');
        friendUUID = self.username_to_uid(data, friendUsername)
        if friendUUID is not False and\
           friendUUID in data:
            requestorUsername = self.uid_to_username(data, uid)
            if not 'friendReqs' in data[friendUUID]:
                data[friendUUID]['friendReqs'] = []
            if not 'friendReqs' in data[uid]:
                data[uid]['friendReqs'] = []
            if len(data[friendUUID]['friendReqs']) >= 20:
                return (409, 'That person has maxed out their friends!')
            if len(data[uid]['friendReqs']) >= 20:
                return (409, 'You have maxed out their friends!')
            if uid == friendUUID:
                return (409, 'You can\'t add yourself as a friend.')
            if friendUUID in data[uid]['friendReqs']:
                if not 'friends' in data[friendUUID]:
                    data[friendUUID]['friends'] = []
                if not 'friends' in data[uid]:
                    data[uid]['friends'] = []

                # Yay! Friend request acception time!
                print('mutual acception', uid, friendUUID)
                try:
                    data[friendUUID]['friends'] += [uid]
                    data[uid]['friends'] += [friendUUID]
                    data[friendUUID]['friends'] = list(set(data[friendUUID]['friends']))
                    data[uid]['friends'] = list(set(data[uid]['friends']))
                    if uid in data[friendUUID]['friendReqs']:
                        data[friendUUID]['friendReqs'].remove(uid)
                    if friendUUID in data[uid]['friendReqs']:
                        data[uid]['friendReqs'].remove(friendUUID)
                    for _uuid, _username in [(uid, friendUsername),
                                             (friendUUID, requestorUsername)]:
                        pinId = 'friend-request-' + str(random.randint(10**8, 10**9))
                        self.pin(data, _uuid, {
                            'time': time.strftime("%Y-%m-%dT%H:%M:%S"),
                            'id': pinId,
                            'layout': {
                                'type': 'genericPin',
                                'title': 'New Friend!',
                                'subtitle': 'Step Up!',
                                'body': _username + ' is now your friend on Step Up!'
                            },
                            'createNotification': {
                                'layout': {
                                    'type': 'genericNotification',
                                    'title': 'New Friend!',
                                    'body': 'You and ' + _username + ' are now friends on Step Up!'
                                }
                            }
                        }, pinId)
                except ValueError as e:
                    print(e)
                self.write_data(data)
                return (200, 'OK')
            else:
                # Let's go make some friends!
                data[friendUUID]['friendReqs'] += [uid]
                data[friendUUID]['friendReqs'] = list(set(data[friendUUID]['friendReqs']))
                self.write_data(data)
                try:
                    pinId = 'friend-request-' + str(random.randint(10**8, 10**9))
                    self.pin(data, friendUUID, {
                        'time': time.strftime("%Y-%m-%dT%H:%M:%S"),
                        'id': pinId,
                        'layout': {
                            'type': 'genericPin',
                            'title': 'Friend Request!',
                            'subtitle': 'Step Up!',
                            'body': requestorUsername + ' wants to be your friend on Step Up!'
                        },
                        'createNotification': {
                            'layout': {
                                'type': 'genericNotification',
                                'title': 'Friend Request!',
                                'body': requestorUsername +
                                    ' wants to be your friend on Step Up!\n' +
                                    'Select "More" from actions to accept.'
                            }
                        },
                        'actions': [
                            {
                                'type': 'http',
                                'method': 'GET',
                                'title': 'Accept',
                                'url': self.get_own_api_root() +
                                       'send_friend_request?uid=' + friendUUID +
                                       '&addusername=' + requestorUsername
                            }
                        ]
                    }, pinId)
                except urllib.error.HTTPError as e:
                    return (200, 'pin sending failure: ' + e.read().decode('utf-8'))
                return (200, 'OK')
        else:
            return (400, 'Friending user doesn\'t exist.')

    def delete_friend(self, uid, friendUsername):
        data = self.get_data()
        if not uid in data:
            data[uid] = {}
        if not 'friends' in data[uid]:
            data[uid]['friends'] = []
        friendUUID = self.username_to_uid(data, friendUsername)
        requestorUsername = self.uid_to_username(data, uid)

        data[uid]['friends'] = list(set(data[uid]['friends']))
        if friendUUID in data[uid]['friends']:
            data[uid]['friends'].remove(friendUUID)

        if not friendUUID is False:
            data[friendUUID]['friends'] = list(set(data[friendUUID]['friends']))
            if uid in data[friendUUID]['friends']:
                data[friendUUID]['friends'].remove(uid)

            self.write_data(data)
            return (200, 'OK')
        else:
            return (400, 'User doesn\'t exist.')

    def dump_data(self):
        data = self.get_data()
        out = '<!DOCTYPE html>'
        for key, value in sorted(data.items(), key=lambda x: x[0]):
            out += '' + key + '' +\
                   '
'
            for propKey, propVal in sorted(value.items(), key=lambda x: x[0]):
                out += '' + propKey + ': ' +\
                       '' + json.dumps(propVal) + '
'
            out += '
'
        out += ''
        return (200, out)

    def end_headers(self):
        self.send_header('Access-Control-Allow-Origin', '*')
        BaseHTTPRequestHandler.end_headers(self)

    def do_GET(self):
        urldata = urllib.parse.urlparse(self.path)
        qdata = urllib.parse.parse_qs(urldata.query)
        print(qdata)
        try:
            self.path.index('/dump')
            try:
                # NB this removes it in prod
                assert not 'OPENSHIFT_PYTHON_IP' in os.environ
                info = self.dump_data()
                print(info)
                self.respond(info[0], info[1])
                return
            except AssertionError:
                pass
        except ValueError:
            pass
        try:
            self.path.index('/username_in_use')
            try:
                assert 'username' in qdata
                info = self.username_in_use(qdata['username'][0])
                self.respond(200, json.dumps(str(info)))
            except AssertionError:
                self.respond(400, 'Malformed Request')
                return
        except ValueError:
            pass
        try:
            self.path.index('/add_data')
            try:
                assert 'uid' in qdata and\
                       'timeperiod' in qdata and\
                       'steps' in qdata
                info = self.add_data_point(qdata['uid'][0],
                                           qdata['timeperiod'][0],
                                           qdata['steps'][0])
                if (len(info) == 2):
                    self.respond(info[0], info[1])
            except AssertionError:
                self.respond(400, 'Malformed Request')
                return
        except ValueError:
            pass
        try:
            self.path.index('/send_friend_request')
            try:
                assert 'uid' in qdata and\
                       'addusername' in qdata
                info = self.send_friend_request(qdata['uid'][0],
                                                qdata['addusername'][0])
                if (len(info) == 2):
                    self.respond(info[0], info[1])
                    return
            except AssertionError:
                self.respond(400, 'Malformed Request')
                return
        except ValueError:
            pass
        try:
            self.path.index('/get_friends')
            try:
                assert 'uid' in qdata
                info = self.get_friends(qdata['uid'][0])
                self.respond(info[0], info[1])
            except AssertionError:
                self.respond(400, 'Malformed request')
            return
        except ValueError:
            pass
        try:
            self.path.index('/delete_friend')
            try:
                assert 'uid' in qdata and\
                       'deleteusername' in qdata
                info = self.delete_friend(qdata['uid'][0],
                                          qdata['deleteusername'][0])
                self.respond(info[0], info[1])
            except AssertionError:
                self.respond(400, 'Malformed request')
            return
        except ValueError:
            pass
        try:
            self.path.index('/get_username')
            try:
                assert 'uid' in qdata
                print(self.path)
                username = self.uid_to_username(self.get_data(), qdata['uid'][0])
                if username is not False:
                    self.respond(200, json.dumps(username))
                else:
                    self.respond(404, 'User not registered')
                return
            except AssertionError:
                self.respond(400, 'Malformed request')
                return
        except ValueError:
            pass
        try:
            self.path.index('/set_username')
            try:
                assert 'uid' in qdata and\
                       'username' in qdata
                print(self.path)
                info = self.set_username(qdata['uid'][0], qdata['username'][0])
                self.respond(info[0], info[1])
                return
            except AssertionError:
                self.respond(400, 'Malformed request')
                return
        except ValueError:
            pass
        try:
            self.path.index('/set_timeline_token')
            try:
                assert 'uid' in qdata and\
                       'tltoken' in qdata
                print(self.path)
                info = self.set_timeline_token(qdata['uid'][0], qdata['tltoken'][0])
                self.respond(info[0], info[1])
                return
            except AssertionError:
                self.respond(400, 'Malformed request')
                return
        except ValueError:
            pass
        self.respond(400, 'Method missing')

if __name__ == '__main__':
    if 'OPENSHIFT_PYTHON_IP' in os.environ:
        server_address = (os.environ['OPENSHIFT_PYTHON_IP'],
                          int(os.environ['OPENSHIFT_PYTHON_PORT']))
    else:
        server_address = ('', 8080)
    httpd = HTTPServer(server_address, RequestHandler)
    httpd.serve_forever()
<|endoftext|>


<commit_before>from flask import Flask, request, session, g, redirect, url_for, abort, \
     render_template, flash

import subprocess

app = Flask(__name__)

@app.route("/")
def main():
	#flash('Hi')
	return render_template('main.html')

@app.route('/enqueue/youtube', methods=['POST'])
def enqueue():

	# this is experimental, replace with mpv.py or ipc something:
	#os.system("sudo -u realraum mpv --no-video  %s" % request.form['url'])
	#ret = subprocess.call(["sudo", "-u", "realraum", "mpv", "--no-video", request.form['url']])
	ret = subprocess.call(["mpv", "--no-video", request.form['url']])

	return "OK: %s (%d)" % (request.form['url'], ret)

if __name__ == "__main__":
	app.debug = True
	app.run(host='0.0.0.0')
<commit_msg>added youtube title resolving<commit_after>from flask import Flask, request, session, g, redirect, url_for, abort, \
     render_template, flash, json, jsonify

from urlparse import urlparse, parse_qs

import urllib2
import subprocess

app = Flask(__name__)

queue = []

def getYouTubeID(videoURL):
	app.logger.debug('getting videoID: ' + videoURL)
	return parse_qs(urlparse(videoURL).query)['v'][0]

def getYouTubeTitle(videoId):
	app.logger.debug('getting title for videoId: ' + videoId)
	response = urllib2.urlopen("http://youtube.com/get_video_info?video_id=" + str(videoId))

	query = urlparse("/?" + response.read()).query

	return parse_qs(query)['title'][0]

@app.route("/")
def main():
	#flash('Hi')
	return render_template('main.html')

@app.route('/queue', methods=['GET'])
def getQueue():
	return jsonify(queue=queue)

@app.route('/enqueue/youtube', methods=['POST'])
def enqueue():

	app.logger.debug('/enqueue/youtube ...')

	# this is experimental, replace with mpv.py or ipc something:
	#os.system("sudo -u realraum mpv --no-video  %s" % request.form['url'])
	#ret = subprocess.call(["sudo", "-u", "realraum", "mpv", "--no-video", request.form['url']])

	# ret = subprocess.call(["mpv", "--no-video", request.form['url']])

	videoID = getYouTubeID(request.form['url'])

	title = getYouTubeTitle(videoID)

	queue.append({    'type': 'YT',
					 'title': title,
					'artist': 'YouTube'})

	return "OK: %d" % len(queue)

if __name__ == "__main__":
	app.debug = True
	app.run(host='0.0.0.0')
<|endoftext|>


<commit_before>from flask import Flask, render_template, jsonify, request, json, redirect
from db import Body, Request, Document, RequestTag, get_session
from sqlalchemy import and_, or_

app = Flask(__name__)

@app.route('/')
def index():
    return render_template("index.html")

@app.route('/requests')
def requests():
    db = get_session()
    reqs = db.query(Request).all()
    return render_template("requests.html", reqs=reqs[0:20])

@app.route('/request/<req_id>')
def request_details(req_id):
    db = get_session()
    req = db.query(Request).get(req_id)
    docs = db.query(Document).filter(Document.request == req.id).all()
    if len(docs) > 0:
        doc = docs[0]
    else:
        doc = False
    body = db.query(Body).get(req.body)
    tags = [t.tag for t in db.query(RequestTag).filter(RequestTag.request == req.id)]
    return render_template("request.html", req=req, doc = doc, body=body,
                           tags=tags)

@app.route('/request/search/<query>')
def search(query):
    db = get_session()
    query = '%{0}%'.format(query)
    reqs = db.query(Request).filter(Request.title.ilike(query))
    return render_template("requests.html", reqs=reqs)

@app.route('/api/all')
def api_all():
    db = get_session()
    reqs = db.query(Request).all()
    return jsonify({'requests': [r.get_public() for r in reqs]})

@app.route('/api/search')
def api_search():
    db = get_session()
    sterms = request.args.get('q')
    if sterms:
        sterms = sterms.split(',')
    else:
        return jsonify({'error': "Search term is required."})
    if len(sterms) == 0:
        return jsonify({"error": "No search terms."})
    qterms = [or_(Request.title.ilike("%{0}%".format(t)),
                  RequestTag.tag.ilike("%{0}%".format(t))) for t in sterms]
    res = db.query(Request).join(RequestTag).filter(and_(*qterms))
    locs = request.args.get('l')
    if locs:
        locs = locs.split(',')
        lterms = [Body.name.ilike("%{0}%".format(l)) for l in locs]
        res  = res.join(Body).filter(or_(*lterms))
    return jsonify({'requests': [r.get_public() for r in res.all()]})

<commit_msg>Add API endoint to get document(s) for a request.<commit_after>from flask import Flask, render_template, jsonify, request, json, redirect
from db import Body, Request, Document, RequestTag, get_session
from sqlalchemy import and_, or_

app = Flask(__name__)

@app.route('/')
def index():
    return render_template("index.html")

@app.route('/requests')
def requests():
    db = get_session()
    reqs = db.query(Request).all()
    return render_template("requests.html", reqs=reqs[0:20])

@app.route('/request/<req_id>')
def request_details(req_id):
    db = get_session()
    req = db.query(Request).get(req_id)
    docs = db.query(Document).filter(Document.request == req.id).all()
    if len(docs) > 0:
        doc = docs[0]
    else:
        doc = False
    body = db.query(Body).get(req.body)
    tags = [t.tag for t in db.query(RequestTag).filter(RequestTag.request == req.id)]
    return render_template("request.html", req=req, doc = doc, body=body,
                           tags=tags)

@app.route('/request/search/<query>')
def search(query):
    db = get_session()
    query = '%{0}%'.format(query)
    reqs = db.query(Request).filter(Request.title.ilike(query))
    return render_template("requests.html", reqs=reqs)

@app.route('/api/all')
def api_all():
    db = get_session()
    reqs = db.query(Request).all()
    return jsonify({'requests': [r.get_public() for r in reqs]})

@app.route('/api/search')
def api_search():
    db = get_session()
    sterms = request.args.get('q')
    if sterms:
        sterms = sterms.split(',')
    else:
        return jsonify({'error': "Search term is required."})
    if len(sterms) == 0:
        return jsonify({"error": "No search terms."})
    qterms = [or_(Request.title.ilike("%{0}%".format(t)),
                  RequestTag.tag.ilike("%{0}%".format(t))) for t in sterms]
    res = db.query(Request).join(RequestTag).filter(and_(*qterms))
    locs = request.args.get('l')
    if locs:
        locs = locs.split(',')
        lterms = [Body.name.ilike("%{0}%".format(l)) for l in locs]
        res  = res.join(Body).filter(or_(*lterms))
    return jsonify({'requests': [r.get_public() for r in res.all()]})

@app.route('/api/documents/<int:req_id>')
def api_document(req_id):
    db = get_session()
    docs = db.query(Document).filter(Document.request == req_id).all()
    docs = [{'id': d.id, 'url': d.url, 'req_id': d.request, 'text':d.text} for d in docs]
    return jsonify({'documents': docs})
<|endoftext|>


<commit_before>#!/usr/bin/env python
import peewee
from flask import Flask, g, render_template, request, redirect, url_for
from flask.ext.misaka import Misaka
from argparse import ArgumentParser
import logging
import re
import urlparse
import urllib
import bleach
import git
import os

import settings

app = Flask(__name__)
Misaka(app)

database = peewee.SqliteDatabase(settings.DATABASE, threadlocals=True)

@app.context_processor
def add_git_version():
    repo = git.Repo(os.path.dirname(os.path.realpath(__file__)))
    return dict(git_version=repo.head.commit.hexsha)

@app.context_processor
def add_random_page():
    page = None
    try:
        page = Page.select().order_by(peewee.fn.Random()).limit(1)[0]
    except:
        pass
    return dict(random_page=page)

@app.context_processor
def add_site_settings():
    return dict(settings=settings)

tag_whitelist = [
  'ul', 'li', 'ol', 'p', 'table', 'div', 'tr', 'th', 'td', 'em', 'big', 'b',
  'strong', 'a', 'abbr', 'aside', 'audio', 'blockquote', 'br', 'button', 'code',
  'dd', 'del', 'dfn', 'dl', 'dt', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i',
  'img', 'ins', 'kbd', 'pre', 's', 'small', 'span', 'sub', 'sup', 'u', 'video'
]
@app.template_filter('safetags')
def safetags(s):
    return bleach.clean(s, tags=tag_whitelist, strip_comments=False)

linkSyntax = re.compile("\[\[(.+?)\]\]")
titledLinkSyntax = re.compile("\[\[(.+?)\|(.+?)\]\]")
def make_wikilink(match):
    groups = match.groups()
    if len(groups) == 1:
        title = groups[0]
        link = groups[0]
    else:
        title = groups[1]
        link = groups[0]
    return "[%s](%s)"%(title, link)

@app.template_filter('wikilinks')
def wikilinks(s):
    s = titledLinkSyntax.sub(make_wikilink, s)
    s = linkSyntax.sub(make_wikilink, s)
    return s

@app.before_request
def setup_db():
    g._database = database
    g._database.connect()

@app.teardown_appcontext
def close_db(error):
    if hasattr(g, '_database'):
        try:
            g._database.close()
        except:
            pass
        del g._database

class BaseModel(peewee.Model):
    class Meta:
        database = database

class Page(BaseModel):
    title = peewee.CharField(unique=True)
    slug = peewee.CharField(unique=True)

    def newRevision(self, body):
        return Revision.create(page=self, body=body)

    def makeSoftlinkFrom(self, prev):
        logging.debug("Linking from %s to %s", prev.slug, self.slug)
        try:
            Softlink.get(Softlink.src == prev, Softlink.dest == self)
            logging.debug("Link exists!")
        except peewee.DoesNotExist:
            Softlink.create(src=prev, dest=self)
            logging.debug("New link!")
        Softlink.update(hits = Softlink.hits + 1).where(Softlink.src ==
            prev, Softlink.dest == self).execute()

    @classmethod
    def latestRevision(cls, slug):
        try:
            return Revision.select() \
                .join(cls) \
                .where(cls.slug == slug) \
                .order_by(Revision.id.desc())[0]
        except IndexError:
            return None

class Softlink(BaseModel):
    src = peewee.ForeignKeyField(Page, related_name='softlinks_out')
    dest = peewee.ForeignKeyField(Page, related_name='softlinks_in')
    hits = peewee.IntegerField(default=0)

class Revision(BaseModel):
    page = peewee.ForeignKeyField(Page, related_name='revisions')
    body = peewee.TextField()

@app.route("/.history/<slug>")
def history(slug):
    page = Page.get(slug=slug)
    return render_template('history.html', page=page)

@app.route('/.revision/<revision>')
def revision(revision):
    revision = Revision.get(id=revision)
    return render_template('revision.html', revision=revision)

@app.route("/.save", methods=['POST'])
def save():
    try:
      page = Page.get(slug=request.form['title'])
    except peewee.DoesNotExist:
      page = Page.create(slug=request.form['title'],
          title=request.form['title'])
    rev = page.newRevision(request.form['body'])
    return redirect(url_for('index', slug=request.form['title']))

@app.route("/.edit/<slug>", methods=['GET'])
def edit(slug):
    revision = Page.latestRevision(slug)
    if revision is not None:
        return render_template('edit.html',
            revision=revision)
    else:
        return render_template('404.html',
            slug=slug)

@app.route("/.search")
def search():
    query = request.args.get('q')
    pages = Page.select().where(Page.title.contains(query))
    return render_template('search.html', results=pages, query=query)

@app.route("/.all-pages")
def allPages():
    pages = Page.select().order_by(Page.title)
    return render_template('all-pages.html',
        pages=pages)

@app.route("/")
@app.route("/<slug>")
def index(slug=settings.INDEX_PAGE, redirectFrom=None):
    lastPage = None
    revision = Page.latestRevision(slug)

    if 'Referer' in request.headers:
        referer = request.headers['Referer']
        referUrl = urlparse.urlparse(referer)
        if referUrl.netloc == request.headers['Host']:
            lastPageSlug = urllib.unquote(referUrl.path[1:])
            logging.debug("Last page slug: %s", lastPageSlug)
            if lastPageSlug != settings.INDEX_PAGE:
                try:
                    lastPage = Page.get(slug=lastPageSlug)
                except peewee.DoesNotExist:
                    pass

    if revision is not None:
        if lastPage is not None and lastPage != revision.page:
            revision.page.makeSoftlinkFrom(lastPage)

        if revision.body.startswith("#Redirect"):
            newSlug = revision.body.split(' ', 1)[1]
            logging.debug("Redirect to %s", newSlug)
            return index(newSlug, redirectFrom=slug)
        return render_template('page.html',
            revision=revision, redirectFrom=redirectFrom)
    else:
        return render_template('404.html',
            slug=slug, redirectFrom=redirectFrom)

if __name__ == "__main__":
    parser = ArgumentParser()
    parser.add_argument('--syncdb', action='store_const',
        default=False, const=True)
    args = parser.parse_args()

    logging.basicConfig(level=logging.DEBUG)

    if args.syncdb:
      logging.info("Creating tables...")
      with app.app_context():
        database.create_tables([Page, Revision, Softlink])
      logging.info("OK!")
    else:
      app.run(debug=True)
<commit_msg>Universal slugification<commit_after>#!/usr/bin/env python
import peewee
from flask import Flask, g, render_template, request, redirect, url_for
from flask.ext.misaka import Misaka
from argparse import ArgumentParser
import logging
import re
import urlparse
import urllib
import bleach
import git
import os

import settings

app = Flask(__name__)
Misaka(app)

database = peewee.SqliteDatabase(settings.DATABASE, threadlocals=True)

@app.context_processor
def add_git_version():
    repo = git.Repo(os.path.dirname(os.path.realpath(__file__)))
    return dict(git_version=repo.head.commit.hexsha)

@app.context_processor
def add_random_page():
    page = None
    try:
        page = Page.select().order_by(peewee.fn.Random()).limit(1)[0]
    except:
        pass
    return dict(random_page=page)

@app.context_processor
def add_site_settings():
    return dict(settings=settings)

tag_whitelist = [
  'ul', 'li', 'ol', 'p', 'table', 'div', 'tr', 'th', 'td', 'em', 'big', 'b',
  'strong', 'a', 'abbr', 'aside', 'audio', 'blockquote', 'br', 'button', 'code',
  'dd', 'del', 'dfn', 'dl', 'dt', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i',
  'img', 'ins', 'kbd', 'pre', 's', 'small', 'span', 'sub', 'sup', 'u', 'video'
]
@app.template_filter('safetags')
def safetags(s):
    return bleach.clean(s, tags=tag_whitelist, strip_comments=False)

linkSyntax = re.compile("\[\[(.+?)\]\]")
titledLinkSyntax = re.compile("\[\[(.+?)\|(.+?)\]\]")
def make_wikilink(match):
    groups = match.groups()
    if len(groups) == 1:
        title = groups[0]
        link = groups[0]
    else:
        title = groups[1]
        link = groups[0]
    return "[%s](%s)"%(title, link)

@app.template_filter('wikilinks')
def wikilinks(s):
    s = titledLinkSyntax.sub(make_wikilink, s)
    s = linkSyntax.sub(make_wikilink, s)
    return s

@app.before_request
def setup_db():
    g._database = database
    g._database.connect()

@app.teardown_appcontext
def close_db(error):
    if hasattr(g, '_database'):
        try:
            g._database.close()
        except:
            pass
        del g._database

class BaseModel(peewee.Model):
    class Meta:
        database = database

class SlugField(peewee.CharField):
    def coerce(self, value):
        return self.slugify(value)

    @staticmethod
    def slugify(title):
        return re.sub('[^\w]', '_', title.lower())

class Page(BaseModel):
    title = peewee.CharField(unique=True)
    slug = SlugField(unique=True)

    def newRevision(self, body):
        return Revision.create(page=self, body=body)

    def makeSoftlinkFrom(self, prev):
        logging.debug("Linking from %s to %s", prev.slug, self.slug)
        try:
            Softlink.get(Softlink.src == prev, Softlink.dest == self)
            logging.debug("Link exists!")
        except peewee.DoesNotExist:
            Softlink.create(src=prev, dest=self)
            logging.debug("New link!")
        Softlink.update(hits = Softlink.hits + 1).where(Softlink.src ==
            prev, Softlink.dest == self).execute()

    @classmethod
    def latestRevision(cls, slug):
        try:
            return Revision.select() \
                .join(cls) \
                .where(cls.slug == slug) \
                .order_by(Revision.id.desc())[0]
        except IndexError:
            return None

class Softlink(BaseModel):
    src = peewee.ForeignKeyField(Page, related_name='softlinks_out')
    dest = peewee.ForeignKeyField(Page, related_name='softlinks_in')
    hits = peewee.IntegerField(default=0)

class Revision(BaseModel):
    page = peewee.ForeignKeyField(Page, related_name='revisions')
    body = peewee.TextField()

@app.route("/.history/<slug>")
def history(slug):
    page = Page.get(slug=slug)
    return render_template('history.html', page=page)

@app.route('/.revision/<revision>')
def revision(revision):
    revision = Revision.get(id=revision)
    return render_template('revision.html', revision=revision)

@app.route("/.save", methods=['POST'])
def save():
    try:
      page = Page.get(slug=request.form['title'])
    except peewee.DoesNotExist:
      page = Page.create(slug=request.form['title'],
          title=request.form['title'])
    rev = page.newRevision(request.form['body'])
    return redirect(url_for('index', slug=request.form['title']))

@app.route("/.edit/<slug>", methods=['GET'])
def edit(slug):
    revision = Page.latestRevision(slug)
    if revision is not None:
        return render_template('edit.html',
            revision=revision)
    else:
        return render_template('404.html',
            slug=slug)

@app.route("/.search")
def search():
    query = request.args.get('q')
    pages = Page.select().where(Page.title.contains(query))
    return render_template('search.html', results=pages, query=query)

@app.route("/.all-pages")
def allPages():
    pages = Page.select().order_by(Page.title)
    return render_template('all-pages.html',
        pages=pages)

@app.route("/")
@app.route("/<slug>")
def index(slug=settings.INDEX_PAGE, redirectFrom=None):
    lastPage = None
    revision = Page.latestRevision(slug)

    if 'Referer' in request.headers:
        referer = request.headers['Referer']
        referUrl = urlparse.urlparse(referer)
        if referUrl.netloc == request.headers['Host']:
            lastPageSlug = urllib.unquote(referUrl.path[1:])
            logging.debug("Last page slug: %s", lastPageSlug)
            if lastPageSlug != settings.INDEX_PAGE:
                try:
                    lastPage = Page.get(slug=lastPageSlug)
                except peewee.DoesNotExist:
                    pass

    if revision is not None:
        if lastPage is not None and lastPage != revision.page:
            revision.page.makeSoftlinkFrom(lastPage)

        if revision.body.startswith("#Redirect"):
            newSlug = revision.body.split(' ', 1)[1]
            logging.debug("Redirect to %s", newSlug)
            return index(newSlug, redirectFrom=slug)
        return render_template('page.html',
            revision=revision, redirectFrom=redirectFrom)
    else:
        return render_template('404.html',
            slug=slug, redirectFrom=redirectFrom)

if __name__ == "__main__":
    parser = ArgumentParser()
    parser.add_argument('--syncdb', action='store_const',
        default=False, const=True)
    args = parser.parse_args()

    logging.basicConfig(level=logging.DEBUG)

    if args.syncdb:
      logging.info("Creating tables...")
      with app.app_context():
        database.create_tables([Page, Revision, Softlink])
      logging.info("OK!")
    else:
      app.run(debug=True)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import argparse
import random
import os

import cherrypy

from ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketTool
from ws4py.websocket import WebSocket
from ws4py.messaging import TextMessage

class ChatWebSocketHandler(WebSocket):
    def received_message(self, m):
        cherrypy.engine.publish('websocket-broadcast', m)

    def closed(self, code, reason="A client left the room without a proper explanation."):
        cherrypy.engine.publish('websocket-broadcast', TextMessage(reason))

class Root(object):
    def __init__(self, host, port, ssl=False):
        self.host = host
        self.port = port
        self.scheme = 'wss' if ssl else 'ws'

    @cherrypy.expose
    def index(self):
        return """

    <form action='#' id='chatform' method='get'>
      <textarea id='chat' cols='35' rows='10'></textarea>

      %(username)s: <input type='text' id='message' />
      <input id='send' type='submit' value='Send' />
      </form>

    """ % {'username': "User%d" % random.randint(0, 100), 'host': self.host, 'port': self.port, 'scheme': self.scheme}

    @cherrypy.expose
    def ws(self):
        cherrypy.log("Handler created: %s" % repr(cherrypy.request.ws_handler))

if __name__ == '__main__':
    import logging
    from ws4py import configure_logger
    configure_logger(level=logging.DEBUG)

    parser = argparse.ArgumentParser(description='Echo CherryPy Server')
    parser.add_argument('--host', default='127.0.0.1')
    parser.add_argument('-p', '--port', default=9000, type=int)
    parser.add_argument('--ssl', action='store_true')
    args = parser.parse_args()

    cherrypy.config.update({'server.socket_host': args.host,
                            'server.socket_port': args.port,
                            'tools.staticdir.root': os.path.abspath(os.path.join(os.path.dirname(__file__), 'static'))})

    if args.ssl:
        cherrypy.config.update({'server.ssl_certificate': './server.crt',
                                'server.ssl_private_key': './server.key'})

    WebSocketPlugin(cherrypy.engine).subscribe()
    cherrypy.tools.websocket = WebSocketTool()

    cherrypy.quickstart(Root(args.host, args.port, args.ssl), '', config={
        '/ws': {
            'tools.websocket.on': True,
            'tools.websocket.handler_cls': ChatWebSocketHandler
            },
        '/js': {
              'tools.staticdir.on': True,
              'tools.staticdir.dir': 'js'
            }
        }
    )
<commit_msg>add autoscrolling<commit_after># -*- coding: utf-8 -*-
import argparse
import random
import os

import cherrypy

from ws4py.server.cherrypyserver import WebSocketPlugin, WebSocketTool
from ws4py.websocket import WebSocket
from ws4py.messaging import TextMessage

class ChatWebSocketHandler(WebSocket):
    def received_message(self, m):
        cherrypy.engine.publish('websocket-broadcast', m)

    def closed(self, code, reason="A client left the room without a proper explanation."):
        cherrypy.engine.publish('websocket-broadcast', TextMessage(reason))

class Root(object):
    def __init__(self, host, port, ssl=False):
        self.host = host
        self.port = port
        self.scheme = 'wss' if ssl else 'ws'

    @cherrypy.expose
    def index(self):
        return """

MockingJay

    <form action='#' id='chatform' method='get'>
      <textarea id='chat' cols='35' rows='10'></textarea>

      %(username)s: <input type='text' id='message' />
      <input id='send' type='submit' value='Send' />
      </form>

    """ % {'username': "User%d" % random.randint(0, 100), 'host': self.host, 'port': self.port, 'scheme': self.scheme}

    @cherrypy.expose
    def ws(self):
        cherrypy.log("Handler created: %s" % repr(cherrypy.request.ws_handler))

if __name__ == '__main__':
    import logging
    from ws4py import configure_logger
    configure_logger(level=logging.DEBUG)

    parser = argparse.ArgumentParser(description='Echo CherryPy Server')
    parser.add_argument('--host', default='127.0.0.1')
    parser.add_argument('-p', '--port', default=9000, type=int)
    parser.add_argument('--ssl', action='store_true')
    args = parser.parse_args()

    cherrypy.config.update({'server.socket_host': args.host,
                            'server.socket_port': args.port,
                            'tools.staticdir.root': os.path.abspath(os.path.join(os.path.dirname(__file__), 'static'))})

    if args.ssl:
        cherrypy.config.update({'server.ssl_certificate': './server.crt',
                                'server.ssl_private_key': './server.key'})

    WebSocketPlugin(cherrypy.engine).subscribe()
    cherrypy.tools.websocket = WebSocketTool()

    cherrypy.quickstart(Root(args.host, args.port, args.ssl), '', config={
        '/ws': {
            'tools.websocket.on': True,
            'tools.websocket.handler_cls': ChatWebSocketHandler
            },
        '/js': {
              'tools.staticdir.on': True,
              'tools.staticdir.dir': 'js'
            }
        }
    )
<|endoftext|>


<commit_before>from config import config
from flask import Flask, render_template, request, jsonify, session, url_for, redirect
import requests
import json

app = Flask(__name__)
app.secret_key = "doafkjgasfjk"

_DISCORD_API_BASE = "https://discordapp.com/api/v6"

@app.route("/api/Get_Channel_Messages")
def get_channel_messages():
    channel_id = request.args.get('channel_id')
    after_snowflake = request.args.get('after', None, type=int)
    _endpoint = _DISCORD_API_BASE + "/channels/{channel_id}/messages".format(channel_id=channel_id)
    payload = {}
    if after_snowflake is not None:
        payload = {'after': after_snowflake}
    headers = {'Authorization': 'Bot ' + config['bot-token']}
    r = requests.get(_endpoint, params=payload, headers=headers)
    return jsonify(j=json.loads(r.content))

@app.route("/api/Create_Message", methods=['POST'])
def post_create_message():
    channel_id = request.form.get('channel_id')
    content = request.form.get('content')
    username = session['username']
    _endpoint = _DISCORD_API_BASE + "/channels/{channel_id}/messages".format(channel_id=channel_id)
    payload = {'content': username + ": " + content}
    headers = {'Authorization': 'Bot ' + config['bot-token'], 'Content-Type': 'application/json'}
    r = requests.post(_endpoint, headers=headers, data=json.dumps(payload))
    return jsonify(j=json.loads(r.content))

@app.route("/set_username", methods=["GET"])
def get_set_username():
    return render_template("set_username.html")

@app.route("/set_username", methods=["POST"])
def post_set_username():
    session['username'] = request.form.get('username')
    return redirect(url_for("embed_get", channelid=1))

@app.route("/")
def hello():
    return "This page is not blank"

@app.route("/embed/<channelid>")
def embed_get(channelid):
    if 'username' not in session:
        return redirect(url_for("get_set_username"))
    return render_template("embed.html")

if __name__ == "__main__":
    app.run(host="0.0.0.0",port=3000,debug=True)
<commit_msg>client secret can be the flask secrety key<commit_after>from config import config
from flask import Flask, render_template, request, jsonify, session, url_for, redirect
import requests
import json

app = Flask(__name__)
app.secret_key = config['client-secret']

_DISCORD_API_BASE = "https://discordapp.com/api/v6"

@app.route("/api/Get_Channel_Messages")
def get_channel_messages():
    channel_id = request.args.get('channel_id')
    after_snowflake = request.args.get('after', None, type=int)
    _endpoint = _DISCORD_API_BASE + "/channels/{channel_id}/messages".format(channel_id=channel_id)
    payload = {}
    if after_snowflake is not None:
        payload = {'after': after_snowflake}
    headers = {'Authorization': 'Bot ' + config['bot-token']}
    r = requests.get(_endpoint, params=payload, headers=headers)
    return jsonify(j=json.loads(r.content))

@app.route("/api/Create_Message", methods=['POST'])
def post_create_message():
    channel_id = request.form.get('channel_id')
    content = request.form.get('content')
    username = session['username']
    _endpoint = _DISCORD_API_BASE + "/channels/{channel_id}/messages".format(channel_id=channel_id)
    payload = {'content': username + ": " + content}
    headers = {'Authorization': 'Bot ' + config['bot-token'], 'Content-Type': 'application/json'}
    r = requests.post(_endpoint, headers=headers, data=json.dumps(payload))
    return jsonify(j=json.loads(r.content))

@app.route("/set_username", methods=["GET"])
def get_set_username():
    return render_template("set_username.html")

@app.route("/set_username", methods=["POST"])
def post_set_username():
    session['username'] = request.form.get('username')
    return redirect(url_for("embed_get", channelid=1))

@app.route("/")
def hello():
    return "This page is not blank"

@app.route("/embed/<channelid>")
def embed_get(channelid):
    if 'username' not in session:
        return redirect(url_for("get_set_username"))
    return render_template("embed.html")

if __name__ == "__main__":
    app.run(host="0.0.0.0",port=3000,debug=True)
<|endoftext|>