import json import random from flask import Flask, render_template, redirect, url_for, jsonify, flash from flask.ext.login import LoginManager, login_user, login_required, current_user, logout_user, login_fresh from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.wtf import Form import requests from wtforms import StringField from wtforms.validators import DataRequired from datetime import datetime app = Flask(__name__) app.config.from_pyfile('config.py') login_manager = LoginManager() login_manager.init_app(app) db = SQLAlchemy(app) class LoginForm(Form): api_key = StringField('api_key', validators=[DataRequired()]) class User(db.Model): __tablename__ = 'users' api_key = db.Column(db.String, unique=True, primary_key=True) radicals = db.Column(db.String) kanji = db.Column(db.String) vocabulary = db.Column(db.String) username = db.Column(db.String) gravatar = db.Column(db.String) last_updated = db.Column(db.DateTime) def __init__(self, api_key): self.api_key = api_key self.last_updated = datetime.utcnow() self.parse_radicals_and_userdata() self.parse_kanji() self.parse_vocabulary() db.session.add(self) db.session.commit() def is_authenticated(self): return True def is_active(self): return True def is_anonymous(self): return False def get_id(self): return str(self.api_key) def parse_radicals_and_userdata(self): response = requests.get("https://www.wanikani.com/api/user/" + self.api_key + "/radicals/") response.raise_for_status() data = response.json() if data.get('error'): raise ValueError(data['error']['message']) items = [] self.username = data['user_information']['username'] self.gravatar = data['user_information']['gravatar'] if data.get('requested_information'): for item in data['requested_information']: if item.get('user_specific') and item['user_specific']['burned']: items.append({'character': item['character'], 'meaning': item['meaning'], 'image': item['image']}) self.radicals = json.dumps(items) def parse_kanji(self): response = requests.get("https://www.wanikani.com/api/user/" + self.api_key + "/kanji/") response.raise_for_status() data = response.json() if data.get('error'): raise ValueError(data['error']['message']) items = [] if data.get('requested_information'): for item in data['requested_information']: if item.get('user_specific') and item['user_specific']['burned']: items.append({'character': item['character'], 'meaning': item['meaning'], 'onyomi': item['onyomi'], 'kunyomi': item['kunyomi']}) self.kanji = json.dumps(items) def parse_vocabulary(self): response = requests.get("https://www.wanikani.com/api/user/" + self.api_key + "/vocabulary/") response.raise_for_status() data = response.json() if data.get('error'): raise ValueError(data['error']['message']) items = [] if data.get('requested_information'): for item in data['requested_information']['general']: if item.get('user_specific') and item['user_specific']['burned']: items.append({'character': item['character'], 'meaning': item['meaning'], 'kana': item['kana']}) self.vocabulary = json.dumps(items) def update_all(self): self.parse_radicals_and_userdata() self.parse_kanji() self.parse_vocabulary() self.last_updated = datetime.utcnow() db.session.add(self) db.session.commit() @login_manager.user_loader def load_user(api_key): return User.query.get(str(api_key)) @app.route('/', methods=('GET', 'POST')) def show_home(): if current_user.is_authenticated: return redirect(url_for('show_quiz')) form = LoginForm() if form.validate_on_submit(): user = User.query.get(str(form.api_key.data)) if user: login_user(user) return redirect(url_for('show_quiz')) else: try: new_user = User(str(form.api_key.data)) login_user(new_user) return redirect(url_for('show_quiz')) except ValueError as err: flash(err) return render_template("welcome.html", form=form) return render_template("welcome.html", form=form) @login_required @app.route('/quiz') def show_quiz(): if not login_fresh(): if User.query.get(current_user.api_key): return render_template("quiz.html") else: logout_user() return redirect(url_for('show_home')) return render_template("quiz.html") @app.route('/quiz_item') @login_required def get_quiz(): choices = [] if current_user.radicals: choices.append('radical') if current_user.kanji: choices.append('kanji') if current_user.vocabulary: choices.append('vocabulary') selected_type = random.choice(choices) if selected_type is 'radical': selected_item = random.choice(json.loads(current_user.radicals)) if selected_item['image']: return jsonify(item_type='radical', question=selected_item['image'], answer=selected_item['meaning']) else: return jsonify(item_type='radical', question=selected_item['character'], answer=selected_item['meaning']) elif selected_type is 'kanji': selected_item = random.choice(json.loads(current_user.kanji)) made_answer = "" if selected_item['onyomi'] and selected_item['kunyomi']: made_answer = selected_item['onyomi'] + ',' + selected_item['kunyomi'].replace('.*', '') elif selected_item['onyomi']: made_answer = selected_item['onyomi'] elif selected_item['kunyomi']: made_answer = selected_item['kunyomi'].replace('.*', '') return jsonify(item_type='kanji', question=selected_item['character'], answer=made_answer) else: selected_item = random.choice(json.loads(current_user.vocabulary)) return jsonify(item_type='vocabulary', question=selected_item['character'], answer=selected_item['kana']) @app.route('/refresh', methods=['POST']) def refresh_api(): current_user.update_all() return "202" @app.route('/logout') def logout(): logout_user() return redirect(url_for('show_home')) @login_manager.unauthorized_handler def unauthorized(): return redirect(url_for('show_home')) if __name__ == '__main__': db.create_all() app.debug = True app.run()