mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-02-03 00:31:25 -08:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
3f1bbc82b7
3 changed files with 171 additions and 3 deletions
|
@ -37,6 +37,11 @@
|
||||||
<h5>Import</h5>
|
<h5>Import</h5>
|
||||||
{{ render_field(form.import_file) }}
|
{{ render_field(form.import_file) }}
|
||||||
{{ render_field(form.submit) }}
|
{{ render_field(form.submit) }}
|
||||||
|
<hr>
|
||||||
|
<h5>Export</h5>
|
||||||
|
<p>Export community subscriptions and user settings</p>
|
||||||
|
{{ render_field(form.export_settings) }}
|
||||||
|
<hr>
|
||||||
</form>
|
</form>
|
||||||
<p class="mt-4 pt-4">
|
<p class="mt-4 pt-4">
|
||||||
<a class="btn btn-warning" href="{{ url_for('user.delete_account') }}">{{ _('Delete account') }}</a>
|
<a class="btn btn-warning" href="{{ url_for('user.delete_account') }}">{{ _('Delete account') }}</a>
|
||||||
|
|
|
@ -46,6 +46,7 @@ class SettingsForm(FlaskForm):
|
||||||
manually_approves_followers = BooleanField(_l('Manually approve followers'))
|
manually_approves_followers = BooleanField(_l('Manually approve followers'))
|
||||||
vote_privately = BooleanField(_l('Vote privately'))
|
vote_privately = BooleanField(_l('Vote privately'))
|
||||||
import_file = FileField(_l('Import community subscriptions and user blocks from Lemmy'))
|
import_file = FileField(_l('Import community subscriptions and user blocks from Lemmy'))
|
||||||
|
export_settings = SubmitField(_l('Export'))
|
||||||
sorts = [('hot', _l('Hot')),
|
sorts = [('hot', _l('Hot')),
|
||||||
('top', _l('Top')),
|
('top', _l('Top')),
|
||||||
('new', _l('New')),
|
('new', _l('New')),
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from random import randint
|
from random import randint
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
from flask import redirect, url_for, flash, request, make_response, session, Markup, current_app, abort, json, g
|
from flask import redirect, url_for, flash, request, make_response, session, Markup, current_app, abort, json, g, send_file
|
||||||
from flask_login import login_user, logout_user, current_user, login_required
|
from flask_login import login_user, logout_user, current_user, login_required
|
||||||
from flask_babel import _, lazy_gettext as _l
|
from flask_babel import _, lazy_gettext as _l
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ from app.utils import get_setting, render_template, markdown_to_html, user_acces
|
||||||
blocked_communities
|
blocked_communities
|
||||||
from sqlalchemy import desc, or_, text
|
from sqlalchemy import desc, or_, text
|
||||||
import os
|
import os
|
||||||
|
import json as python_json
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/people', methods=['GET', 'POST'])
|
@bp.route('/people', methods=['GET', 'POST'])
|
||||||
|
@ -210,6 +212,149 @@ def remove_cover():
|
||||||
cache.delete_memoized(User.cover_image, current_user)
|
cache.delete_memoized(User.cover_image, current_user)
|
||||||
return '<div> ' + _('Banner removed!') + '</div>'
|
return '<div> ' + _('Banner removed!') + '</div>'
|
||||||
|
|
||||||
|
# export settings function. used in the /user/settings for a user to export their own settings
|
||||||
|
def export_user_settings(user):
|
||||||
|
# make the empty dict
|
||||||
|
user_dict = {}
|
||||||
|
|
||||||
|
# take the current_user already found
|
||||||
|
# add user's settings to the dict for output
|
||||||
|
# arranaged to match the lemmy settings output order
|
||||||
|
user_dict['display_name'] = user.title
|
||||||
|
user_dict['bio'] = user.about
|
||||||
|
if user.avatar_image() != '':
|
||||||
|
user_dict['avatar'] = f"https://{current_app.config['SERVER_NAME']}/{user.avatar_image()}"
|
||||||
|
if user.cover_image() != '':
|
||||||
|
user_dict['banner'] = f"https://{current_app.config['SERVER_NAME']}/{user.cover_image()}"
|
||||||
|
user_dict['matrix_id'] = user.matrix_user_id
|
||||||
|
user_dict['bot_account'] = user.bot
|
||||||
|
if user.hide_nsfw == 1:
|
||||||
|
lemmy_show_nsfw = False
|
||||||
|
else:
|
||||||
|
lemmy_show_nsfw = True
|
||||||
|
if user.ignore_bots == 1:
|
||||||
|
lemmy_show_bot_accounts = False
|
||||||
|
else:
|
||||||
|
lemmy_show_bot_accounts = True
|
||||||
|
user_dict['settings'] = {
|
||||||
|
"email": f"{user.email}",
|
||||||
|
"show_nsfw": lemmy_show_nsfw,
|
||||||
|
"theme": user.theme,
|
||||||
|
"default_sort_type": f'{user.default_sort}'.capitalize(),
|
||||||
|
"default_listing_type": f'{user.default_filter}'.capitalize(),
|
||||||
|
"interface_language": user.interface_language,
|
||||||
|
"show_bot_accounts": lemmy_show_bot_accounts,
|
||||||
|
# the below items are needed for lemmy to do the import
|
||||||
|
# the "id" and "person_id" are just set to 42
|
||||||
|
# as they expect an int, but it does not override the
|
||||||
|
# existing user's "id" and "public_id"
|
||||||
|
"id": 42,
|
||||||
|
"person_id": 42,
|
||||||
|
"show_avatars": True,
|
||||||
|
"send_notifications_to_email": False,
|
||||||
|
"show_scores": True,
|
||||||
|
"show_bot_accounts": True,
|
||||||
|
"show_read_posts": True,
|
||||||
|
"email_verified": False,
|
||||||
|
"accepted_application": True,
|
||||||
|
"open_links_in_new_tab": False,
|
||||||
|
"blur_nsfw": True,
|
||||||
|
"auto_expand": False,
|
||||||
|
"infinite_scroll_enabled": False,
|
||||||
|
"admin": False,
|
||||||
|
"post_listing_mode": "List",
|
||||||
|
"totp_2fa_enabled": False,
|
||||||
|
"enable_keyboard_navigation": False,
|
||||||
|
"enable_animated_images": True,
|
||||||
|
"collapse_bot_comments": False
|
||||||
|
|
||||||
|
}
|
||||||
|
# get the user subscribed communities' ap_profile_id
|
||||||
|
user_subscribed_communities = []
|
||||||
|
for c in user.communities():
|
||||||
|
if c.ap_profile_id is None:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
user_subscribed_communities.append(c.ap_profile_id)
|
||||||
|
user_dict['followed_communities'] = user_subscribed_communities
|
||||||
|
|
||||||
|
# get bookmarked/saved posts
|
||||||
|
bookmarked_posts = []
|
||||||
|
post_bookmarks = PostBookmark.query.filter_by(user_id=user.id).all()
|
||||||
|
for pb in post_bookmarks:
|
||||||
|
p = Post.query.filter_by(id=pb.post_id).first()
|
||||||
|
bookmarked_posts.append(p.ap_id)
|
||||||
|
user_dict['saved_posts'] = bookmarked_posts
|
||||||
|
|
||||||
|
# get bookmarked/saved comments
|
||||||
|
saved_comments = []
|
||||||
|
post_reply_bookmarks = PostReplyBookmark.query.filter_by(user_id=user.id).all()
|
||||||
|
for prb in post_reply_bookmarks:
|
||||||
|
pr = PostReply.query.filter_by(id=prb.post_reply_id).first()
|
||||||
|
saved_comments.append(pr.ap_id)
|
||||||
|
user_dict['saved_comments'] = saved_comments
|
||||||
|
|
||||||
|
# get blocked communities
|
||||||
|
blocked_communities = []
|
||||||
|
community_blocks = CommunityBlock.query.filter_by(user_id=user.id).all()
|
||||||
|
for cb in community_blocks:
|
||||||
|
c = Community.query.filter_by(id=cb.community_id).first()
|
||||||
|
blocked_communities.append(c.ap_public_url)
|
||||||
|
user_dict['blocked_communities'] = blocked_communities
|
||||||
|
|
||||||
|
# get blocked users
|
||||||
|
blocked_users = []
|
||||||
|
user_blocks = UserBlock.query.filter_by(blocker_id=user.id).all()
|
||||||
|
for ub in user_blocks:
|
||||||
|
blocked_user = User.query.filter_by(id=ub.blocked_id).first()
|
||||||
|
blocked_users.append(blocked_user.ap_public_url)
|
||||||
|
user_dict['blocked_users'] = blocked_users
|
||||||
|
|
||||||
|
# get blocked instances
|
||||||
|
blocked_instances = []
|
||||||
|
instance_blocks = InstanceBlock.query.filter_by(user_id=user.id).all()
|
||||||
|
for ib in instance_blocks:
|
||||||
|
i = Instance.query.filter_by(id=ib.instance_id).first()
|
||||||
|
blocked_instances.append(i.domain)
|
||||||
|
user_dict['blocked_instances'] = blocked_instances
|
||||||
|
|
||||||
|
# piefed versions of (most of) the same settings
|
||||||
|
# TO-DO: adjust the piefed side import method to just take the doubled
|
||||||
|
# settings from the lemmy formatted output. Then remove the duplicate
|
||||||
|
# items here.
|
||||||
|
user_dict['user_name'] = user.user_name
|
||||||
|
user_dict['alt_user_name'] = user.alt_user_name
|
||||||
|
user_dict['title'] = user.title
|
||||||
|
user_dict['email'] = user.email
|
||||||
|
user_dict['about'] = user.about
|
||||||
|
user_dict['about_html'] = user.about_html
|
||||||
|
user_dict['keywords'] = user.keywords
|
||||||
|
user_dict['matrix_user_id'] = user.matrix_user_id
|
||||||
|
user_dict['hide_nsfw'] = user.hide_nsfw
|
||||||
|
user_dict['hide_nsfl'] = user.hide_nsfl
|
||||||
|
user_dict['receive_message_mode'] = user.receive_message_mode
|
||||||
|
user_dict['bot'] = user.bot
|
||||||
|
user_dict['ignore_bots'] = user.ignore_bots
|
||||||
|
user_dict['default_sort'] = user.default_sort
|
||||||
|
user_dict['default_filter'] = user.default_filter
|
||||||
|
user_dict['theme'] = user.theme
|
||||||
|
user_dict['markdown_editor'] = user.markdown_editor
|
||||||
|
user_dict['interface_language'] = user.interface_language
|
||||||
|
user_dict['reply_collapse_threshold'] = user.reply_collapse_threshold
|
||||||
|
if user.avatar_image() != '':
|
||||||
|
user_dict['avatar_image'] = f"https://{current_app.config['SERVER_NAME']}/{user.avatar_image()}"
|
||||||
|
if user.cover_image() != '':
|
||||||
|
user_dict['cover_image'] = f"https://{current_app.config['SERVER_NAME']}/{user.cover_image()}"
|
||||||
|
user_dict['user_blocks'] = blocked_users
|
||||||
|
|
||||||
|
# setup the BytesIO buffer
|
||||||
|
buffer = BytesIO()
|
||||||
|
buffer.write(str(python_json.dumps(user_dict)).encode('utf-8'))
|
||||||
|
buffer.seek(0)
|
||||||
|
|
||||||
|
# pass the buffer back to the calling function, so it can be given to the
|
||||||
|
# user for downloading
|
||||||
|
return buffer
|
||||||
|
|
||||||
@bp.route('/user/settings', methods=['GET', 'POST'])
|
@bp.route('/user/settings', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -227,7 +372,25 @@ def change_settings():
|
||||||
('de', _l('German')),
|
('de', _l('German')),
|
||||||
('ja', _l('Japanese')),
|
('ja', _l('Japanese')),
|
||||||
]
|
]
|
||||||
if form.validate_on_submit():
|
# seperate if to handle just the 'Export' button being clicked
|
||||||
|
if form.export_settings.data and form.validate():
|
||||||
|
# get the user settings for this user
|
||||||
|
buffer = export_user_settings(user)
|
||||||
|
|
||||||
|
# confirmation displayed to user when the page loads up again
|
||||||
|
flash(_l('Export Complete.'))
|
||||||
|
|
||||||
|
# send the file to the user as a download
|
||||||
|
# the as_attachment=True results in flask
|
||||||
|
# redirecting to the current page, so no
|
||||||
|
# url_for needed here
|
||||||
|
return send_file(
|
||||||
|
buffer,
|
||||||
|
download_name=f'{user.user_name}_piefed_settings.json',
|
||||||
|
as_attachment=True,
|
||||||
|
mimetype='application/json'
|
||||||
|
)
|
||||||
|
elif form.validate_on_submit():
|
||||||
propagate_indexable = form.indexable.data != current_user.indexable
|
propagate_indexable = form.indexable.data != current_user.indexable
|
||||||
current_user.newsletter = form.newsletter.data
|
current_user.newsletter = form.newsletter.data
|
||||||
current_user.searchable = form.searchable.data
|
current_user.searchable = form.searchable.data
|
||||||
|
@ -503,7 +666,6 @@ def delete_profile(actor):
|
||||||
goto = request.args.get('redirect') if 'redirect' in request.args else f'/u/{actor}'
|
goto = request.args.get('redirect') if 'redirect' in request.args else f'/u/{actor}'
|
||||||
return redirect(goto)
|
return redirect(goto)
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/instance/<int:instance_id>/unblock', methods=['GET'])
|
@bp.route('/instance/<int:instance_id>/unblock', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def instance_unblock(instance_id):
|
def instance_unblock(instance_id):
|
||||||
|
|
Loading…
Add table
Reference in a new issue