Adding explore endpoint and fixing bugs

This commit is contained in:
Yusur 2019-11-22 18:20:32 +01:00
parent d40a8b9b6b
commit 29cf1532f7
6 changed files with 73 additions and 33 deletions

View file

@ -1,5 +1,13 @@
# Changelog
## 0.9-dev
* Added `create_account` endpoint to API. This endpoint does not require an access token.
* Added `has_more` field to feed endpoints (`feed`, `explore` and `profile_feed`).
* Added `/favicon.ico`.
* Added `explore` endpoint.
* Fixed some bugs when creating mentions and using offsets in feeds.
## 0.8.0
* Added the admin dashboard, accessible from `/admin/` via basic auth. Only users with admin right can access it. Added endpoints `admin.reports` and `admin.reports_detail`.
@ -12,7 +20,7 @@
* Added `relationships_follow`, `relationships_unfollow`, `username_availability`, `edit_profile`, `request_edit` and `confirm_edit` endpoints to API.
* Added `url` utility to model `Upload`.
* Changed default `robots.txt`, adding report and admin-related lines.
* Released official [Android client](https://github.com/sakuragasaki46/coriplusapp/releases/tag/v0.8.0)
* Released official [Android client](https://github.com/sakuragasaki46/coriplusapp/releases/tag/v0.8.0).
## 0.7.1-dev

View file

@ -23,7 +23,7 @@ import datetime, time, re, os, sys, string, json, html
from functools import wraps
from flask_login import LoginManager
__version__ = '0.8.0'
__version__ = '0.9-dev'
# we want to support Python 3 only.
# Python 2 has too many caveats.
@ -69,6 +69,10 @@ def _inject_user(userid):
@app.errorhandler(404)
def error_404(body):
return render_template('404.html'), 404
@app.route('/favicon.ico')
def favicon_ico():
return send_from_directory(os.getcwd(), 'favicon.ico')
@app.route('/robots.txt')
def robots_txt():

View file

@ -1,11 +1,11 @@
from flask import Blueprint, jsonify, request
import sys, os, datetime, re
import sys, os, datetime, re, uuid
from functools import wraps
from peewee import IntegrityError
from .models import User, UserProfile, Message, Upload, Relationship, database, \
MSGPRV_PUBLIC, MSGPRV_UNLISTED, MSGPRV_FRIENDS, MSGPRV_ONLYME, UPLOAD_DIRECTORY
from .utils import check_access_token, Visibility, push_notification, unpush_notification, \
create_mentions, is_username
create_mentions, is_username, generate_access_token, pwdhash
bp = Blueprint('api', __name__, url_prefix='/api/V1')
@ -64,17 +64,33 @@ def feed(self):
if date is None:
date = datetime.datetime.now()
else:
date = datetime.datetime.fromtimestamp(date)
date = datetime.datetime.fromtimestamp(float(date))
query = Visibility(Message
.select()
.where(((Message.user << self.following())
| (Message.user == self))
& (Message.pub_date < date))
.order_by(Message.pub_date.desc())
.limit(20))
for message in query:
.order_by(Message.pub_date.desc()))
for message in query.paginate(1):
timeline_media.append(get_message_info(message))
return {'timeline_media': timeline_media}
return {'timeline_media': timeline_media, 'has_more': query.count() > len(timeline_media)}
@bp.route('/explore')
@validate_access
def explore(self):
timeline_media = []
date = request.args.get('offset')
if date is None:
date = datetime.datetime.now()
else:
date = datetime.datetime.fromtimestamp(float(date))
query = Visibility(Message
.select()
.where(Message.pub_date < date)
.order_by(Message.pub_date.desc()), True)
for message in query.paginate(1):
timeline_media.append(get_message_info(message))
return {'timeline_media': timeline_media, 'has_more': query.count() > len(timeline_media)}
@bp.route('/create', methods=['POST'])
@validate_access
@ -88,7 +104,7 @@ def create(self):
pub_date=datetime.datetime.now(),
privacy=privacy)
# This API does not support files. Use create2 instead.
create_mentions(self, text)
create_mentions(self, text, privacy)
return {}
@bp.route('/create2', methods=['POST'])
@ -110,7 +126,7 @@ def create2(self):
message=message
)
file.save(os.path.join(UPLOAD_DIRECTORY, str(upload.id) + '.' + ext))
create_mentions(self, text)
create_mentions(self, text, privacy)
return {}
def get_relationship_info(self, other):
@ -169,16 +185,15 @@ def profile_feed(self, userid):
if date is None:
date = datetime.datetime.now()
else:
date = datetime.datetime.fromtimestamp(date)
date = datetime.datetime.fromtimestamp(float(date))
query = Visibility(Message
.select()
.where((Message.user == user)
& (Message.pub_date < date))
.order_by(Message.pub_date.desc())
.limit(20))
for message in query:
.order_by(Message.pub_date.desc()))
for message in query.paginate(1):
timeline_media.append(get_message_info(message))
return {'timeline_media': timeline_media}
return {'timeline_media': timeline_media, 'has_more': query.count() > len(timeline_media)}
@bp.route('/relationships/<int:userid>/follow', methods=['POST'])
@validate_access
@ -305,3 +320,31 @@ def save_edit(self, id):
data = request.get_json(True)
Message.update(text=data['text'], privacy=data['privacy']).where(Message.id == id).execute()
return {}
# no validate access for this endpoint!
@bp.route('/create_account', methods=['POST'])
def create_account():
try:
data = request.get_json(True)
try:
birthday = datetime.datetime.fromisoformat(data['birthday'])
except ValueError:
raise ValueError('invalid date format')
username = data['username'].lower()
if not is_username(username):
raise ValueError('invalid username')
with database.atomic():
user = User.create(
username=username,
full_name=data.get('full_name') or username,
password=pwdhash(data['password']),
email=data['email'],
birthday=birthday,
join_date=datetime.datetime.now())
UserProfile.create(
user=user
)
return jsonify({'access_token': generate_access_token(user), 'status': 'ok'})
except Exception as e:
return jsonify({'message': str(e), 'status': 'fail'})

View file

@ -198,7 +198,7 @@ def check_access_token(token):
if h.hexdigest()[:32] == hh:
return user
def create_mentions(cur_user, text):
def create_mentions(cur_user, text, privacy):
# create mentions
mention_usernames = set()
for mo in re.finditer(r'\+([A-Za-z0-9_]+(?:\.[A-Za-z0-9_]+)*)', text):

View file

@ -188,22 +188,7 @@ def create():
message=message
)
file.save(UPLOAD_DIRECTORY + str(upload.id) + '.' + ext)
# create mentions
mention_usernames = set()
for mo in re.finditer(r'\+([A-Za-z0-9_]+(?:\.[A-Za-z0-9_]+)*)', text):
mention_usernames.add(mo.group(1))
# to avoid self mention
mention_usernames.difference_update({user.username})
for u in mention_usernames:
try:
mention_user = User.get(User.username == u)
if privacy in (MSGPRV_PUBLIC, MSGPRV_UNLISTED) or \
(privacy == MSGPRV_FRIENDS and
mention_user.is_following(user) and
user.is_following(mention_user)):
push_notification('mention', mention_user, user=user.id)
except User.DoesNotExist:
pass
create_mentions(user, text, privacy)
flash('Your message has been posted successfully')
return redirect(url_for('website.user_detail', username=user.username))
return render_template('create.html')

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB