2
0
mirror of https://github.com/jfmcbrayer/brutaldon synced 2025-02-10 08:20:40 +01:00
Jason McBrayer 5bdb2de646 Add theme support and move preferences into the database
Squashed commit of the following:

commit be4e1ab286f54caa6f44367d2de3cf9e6cb69e68
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Tue Aug 28 12:03:17 2018 -0400

    Set timezone in session as early as possible

commit f1c03349c40ca1aca7f77c32333ee83585495626
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Tue Aug 28 10:06:18 2018 -0400

    Don't hide all .is-hidden in brutalist themes

commit f35a6c5600b091fe0ec4ad78eb5f1a02a4945a65
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Tue Aug 28 09:44:10 2018 -0400

    Rename vt240don.css to vt240don-amber.css

commit 074478937af309d10ff2d7f8f482dbff20ac7cf9
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Tue Aug 28 09:41:43 2018 -0400

    Tweak vt240 amber theme and add vt240 green theme

commit b205cfe7376d067799863d7db1ce3c4530b0ba74
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Tue Aug 28 08:39:11 2018 -0400

    Remove caching of Mastodon connections

    There's not a good way of invalidating them, and they've started causing
    timeouts in this branch.

commit c24a697a39173ff23391220fabad0dc6605cb5ef
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 14:46:21 2018 -0400

    Make minimal-large a little less bare

commit 6fee850cf6ba1edb573a7fedf43af3a343410c9b
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 14:24:57 2018 -0400

    Add minimal-large theme

commit b345dedbfcf55c3142d07a6f5320c677cfb534f0
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 13:19:51 2018 -0400

    Add vt240don style by @enkiv2

commit f013ff235663ee21f2d0962a019ce7bc3c80f7b0
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 09:15:51 2018 -0400

    Fix crash in search

commit 76c4134e9ddebbdf8a8dccab79361e71438877e6
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 08:35:02 2018 -0400

    Fix crash in oauth_callback

commit d725018d6a34544ac8c92deac27502c457d4d3c8
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 08:31:19 2018 -0400

    Fix crash in oauth_callback

commit 830264359dbdbf7c34e1d1ae715cb68016cd47f4
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 08:28:17 2018 -0400

    Fix crash in oauth_callback

commit 2a525298995d108a290484786a7493bfb99af2c8
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 08:27:03 2018 -0400

    Fix crash in oauth_callback

commit d43eb63146eb21a283290287b9db4d518f36435e
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 08:25:27 2018 -0400

    Fix crash in oauth_callback

commit ae9a58a0ae010fdc12a7498d691b7b8f8da95e03
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 08:12:19 2018 -0400

    Fix up default values for default themes again

commit a8fde1710b4d23f2bdd0ced4eeffd44b4e80b756
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 08:11:18 2018 -0400

    Fixes for dark theme

commit c4a7501cf263afbdc6bf65623e9c8dc5f03f40f7
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Aug 27 08:11:04 2018 -0400

    Small fix in full toot view

commit 69caeea0010e7d59106fba780744592ed9145f61
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Sun Aug 26 22:50:53 2018 -0400

    Fix up settings display, navbar, typo in links

commit 0e24a394eabe78d8cba864beaedb03a42f916a20
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Sun Aug 26 22:36:58 2018 -0400

    Fix default theme paths

commit aca5c53561cd8647d42244fd51720e146fddbf94
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Sun Aug 26 22:35:33 2018 -0400

    More themes prep

commit 6921c55a41db14e155b5ed62c48e3e67d8626b13
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Sun Aug 26 21:42:53 2018 -0400

    Actually load themes

commit 134952ff17e3a8672e21175395282d91f48f1d2b
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Sun Aug 26 21:34:06 2018 -0400

    Base and fullbrutalism themes work, but only coincidentally

commit 658aca52955507eda007165e9c44031d417e0076
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Sun Aug 26 19:47:48 2018 -0400

    Make filtering preference work again

commit 90267055b5a2fc51337b0a3e34b3a5643088e17f
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Sun Aug 26 19:34:47 2018 -0400

    Fix up settings view, form, and model

commit d58769ecdffad239cc8aa37ebca9c2e87372ebd0
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Sun Aug 26 19:12:06 2018 -0400

    Fix up old_login to work with new preferences system

commit d8b084a379894a3a40c3eed1c87465f7c77ad7eb
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Sun Aug 26 18:11:03 2018 -0400

    Update settings view to use preferences system

commit 49471ae97131bdb0d8152411afdf1987d6c64652
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Sat Aug 25 10:53:04 2018 -0400

    Update login logic to match new account models, simplify.

    Not tested yet.

commit 57cce7c0f45fe07dd522a61c9e056db982455843
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Sat Aug 25 10:18:53 2018 -0400

    Fix up models and forms to meet current needs

commit 0634c038ee9220164662d1e933a2f1c83e5af70d
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Fri Aug 24 22:42:07 2018 -0400

    Update fields in models for settings branch

commit 510509e28254cb3ee38b70538d1c0b788448d624
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Fri Jun 22 08:39:42 2018 -0400

    Update settings view a bit; still in progress

commit 5a91a57ceb1d737ed371bd6800ddf6ea0a917a8f
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Tue Jun 19 06:27:19 2018 -0400

    Add forms object for new preferences

commit af4883c172d2b66d83c55b00cee1490fa88ddd4f
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Tue Jun 19 06:26:35 2018 -0400

    Make sure newly created accounts have preferences attached

commit f0ae97b2bf8735bd5c369f273fb51d74deb05450
Author: Jason McBrayer <jmcbray@carcosa.net>
Date:   Mon Jun 18 21:33:41 2018 -0400

    Setup for themes and related options
2018-08-28 12:22:20 -04:00

715 lines
30 KiB
Python

from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.conf import settings as django_settings
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views.decorators.cache import never_cache, cache_page
from django.urls import reverse
from django.core.files.uploadhandler import TemporaryFileUploadHandler
from brutaldon.forms import LoginForm, OAuthLoginForm, PreferencesForm, PostForm
from brutaldon.models import Client, Account, Preference, Theme
from mastodon import Mastodon, AttribAccessDict, MastodonError
from urllib import parse
from pdb import set_trace
class NotLoggedInException(Exception):
pass
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
def get_usercontext(request):
if is_logged_in(request):
try:
client = Client.objects.get(api_base_id=request.session['instance'])
user = Account.objects.get(username=request.session['username'])
except (Client.DoesNotExist, Client.MultipleObjectsReturned,
Account.DoesNotExist, Account.MultipleObjectsReturned):
raise NotLoggedInException()
mastodon = Mastodon(
client_id = client.client_id,
client_secret = client.client_secret,
access_token = user.access_token,
api_base_url = client.api_base_id,
ratelimit_method="throw")
return user, mastodon
else:
return None, None
def is_logged_in(request):
return request.session.has_key('user')
def br_login_required(function=None, home_url=None, redirect_field_name=None):
"""Check that the user is logged in to a Mastodon instance.
This decorator ensures that the view functions it is called on can be
accessed only by logged in users. When an instanceless user accesses
such a protected view, they are redirected to the address specified in
the field named in `next_field` or, lacking such a value, the URL in
`home_url`, or the `ANONYMOUS_HOME_URL` setting.
"""
if home_url is None:
home_url = django_settings.ANONYMOUS_HOME_URL
def _dec(view_func):
def _view(request, *args, **kwargs):
if not is_logged_in(request):
url = None
if redirect_field_name and redirect_field_name in request.REQUEST:
url = request.REQUEST[redirect_field_name]
if not url:
url = home_url
if not url:
url = "/"
return HttpResponseRedirect(url)
else:
return view_func(request, *args, **kwargs)
_view.__name__ = view_func.__name__
_view.__dict__ = view_func.__dict__
_view.__doc__ = view_func.__doc__
return _view
if function is None:
return _dec
else:
return _dec(function)
def timeline(request, timeline='home', timeline_name='Home', max_id=None, since_id=None):
account, mastodon = get_usercontext(request)
data = mastodon.timeline(timeline, limit=100, max_id=max_id, since_id=since_id)
form = PostForm(initial={'visibility': request.session['user'].source.privacy})
try:
prev = data[0]._pagination_prev
if len(mastodon.timeline(since_id=prev['since_id'])) == 0:
prev = None
except (IndexError, AttributeError):
prev = None
try:
next = data[-1]._pagination_next
except (IndexError, AttributeError):
next = None
# This filtering has to be done *after* getting next/prev links
if account.preferences.filter_replies:
data = [x for x in data if not x.in_reply_to_id]
if account.preferences.filter_boosts:
data = [x for x in data if not x.reblog]
return render(request, 'main/%s_timeline.html' % timeline,
{'toots': data, 'form': form, 'timeline': timeline,
'timeline_name': timeline_name,
'own_acct': request.session['user'],
'preferences': account.preferences,
'prev': prev, 'next': next})
@br_login_required
def home(request, next=None, prev=None):
return timeline(request, 'home', 'Home', max_id=next, since_id=prev)
@br_login_required
def local(request, next=None, prev=None):
return timeline(request, 'local', 'Local', max_id=next, since_id=prev)
@br_login_required
def fed(request, next=None, prev=None):
return timeline(request, 'public', 'Federated', max_id=next, since_id=prev)
@br_login_required
def tag(request, tag):
try:
account, mastodon = get_usercontext(request)
except NotLoggedInException:
return redirect(login)
data = mastodon.timeline_hashtag(tag)
return render(request, 'main/timeline.html',
{'toots': data, 'timeline_name': '#'+tag,
'own_acct': request.session['user'],
'preferences': account.preferences})
@never_cache
def login(request):
# User posts instance name in form.
# POST page redirects user to instance, where they log in.
# Instance redirects user to oauth_after_login view.
# oauth_after_login view saves credential in session, then redirects to home.
if request.method == "GET":
form = OAuthLoginForm()
return render(request, 'setup/login-oauth.html', {'form': form})
elif request.method == "POST":
form = OAuthLoginForm(request.POST)
redirect_uris = request.build_absolute_uri(reverse('oauth_callback'))
if form.is_valid():
api_base_url = form.cleaned_data['instance']
tmp_base = parse.urlparse(api_base_url.lower())
if tmp_base.netloc == '':
api_base_url = parse.urlunparse(('https', tmp_base.path,
'','','',''))
else:
api_base_url = api_base_url.lower()
request.session['instance'] = api_base_url
try:
client = Client.objects.get(api_base_id=api_base_url)
except (Client.DoesNotExist, Client.MultipleObjectsReturned):
(client_id, client_secret) = Mastodon.create_app('brutaldon',
api_base_url=api_base_url,
redirect_uris=redirect_uris,
scopes=['read', 'write', 'follow'])
client = Client(
api_base_id = api_base_url,
client_id=client_id,
client_secret = client_secret)
client.save()
request.session['client_id'] = client.client_id
request.session['client_secret'] = client.client_secret
mastodon = Mastodon(
client_id = client.client_id,
client_secret = client.client_secret,
api_base_url = api_base_url)
return redirect(mastodon.auth_request_url(redirect_uris=redirect_uris,
scopes=['read', 'write', 'follow']))
else:
return render(request, 'setup/login.html', {'form': form})
else:
return redirect(login)
@never_cache
def oauth_callback(request):
code = request.GET.get('code', '')
mastodon = Mastodon(client_id=request.session['client_id'],
client_secret=request.session['client_secret'],
api_base_url=request.session['instance'])
redirect_uri = request.build_absolute_uri(reverse('oauth_callback'))
access_token = mastodon.log_in(code=code,
redirect_uri=redirect_uri,
scopes=['read', 'write', 'follow'])
request.session['access_token'] = access_token
user = mastodon.account_verify_credentials()
try:
account = Account.objects.get(username=user.username)
account.access_token = access_token
if not account.preferences:
preferences = Preference(theme = Theme.objects.get(id=1))
preferences.save()
account.preferences = preferences
else:
request.session['timezone'] = account.preferences.timezone
account.save()
except (Account.DoesNotExist, Account.MultipleObjectsReturned):
preferences = Preference(theme = Theme.objects.get(id=1))
preferences.save()
account = Account(username=user.acct,
access_token = access_token,
client = Client.objects.get(api_base_id=request.session['instance']),
preferences = preferences)
request.session['user'] = user
request.session['username'] = user.username
account.username = user.username
account.save()
return redirect(home)
@never_cache
def old_login(request):
if request.method == "GET":
form = LoginForm()
return render(request, 'setup/login.html', {'form': form})
elif request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
api_base_url = form.cleaned_data['instance']
tmp_base = parse.urlparse(api_base_url.lower())
if tmp_base.netloc == '':
api_base_url = parse.urlunparse(('https', tmp_base.path,
'','','',''))
else:
api_base_url = api_base_url.lower()
request.session['instance'] = api_base_url
email = form.cleaned_data['email']
password = form.cleaned_data['password']
try:
client = Client.objects.get(api_base_id=api_base_url)
except (Client.DoesNotExist, Client.MultipleObjectsReturned):
(client_id, client_secret) = Mastodon.create_app('brutaldon',
api_base_url=api_base_url,
scopes=['read', 'write', 'follow'])
client = Client(
api_base_id = api_base_url,
client_id=client_id,
client_secret = client_secret)
client.save()
mastodon = Mastodon(
client_id = client.client_id,
client_secret = client.client_secret,
api_base_url = api_base_url)
try:
account = Account.objects.get(email=email, client_id=client.id)
except (Account.DoesNotExist, Account.MultipleObjectsReturned):
preferences = Preference(theme = Theme.objects.get(id=1))
preferences.save()
account = Account(
email = email,
access_token = "",
client = client,
preferences = preferences)
try:
access_token = mastodon.log_in(username,
password,
scopes=['read', 'write', 'follow'])
account.access_token = access_token
user = mastodon.account_verify_credentials()
request.session['user'] = user
request.session['username'] = user.username
account.username = user.username
request.session['timezone'] = account.preferences.timezone;
account.save()
return redirect(home)
except Exception as ex:
form.add_error('', ex)
return render(request, 'setup/login.html', {'form': form})
else:
return render(request, 'setup/login.html', {'form': form})
@never_cache
def logout(request):
request.session.flush()
return redirect(about)
def error(request):
return render(request, 'error.html', { 'error': "Not logged in yet."})
@br_login_required
def note(request, next=None, prev=None):
try:
account, mastodon = get_usercontext(request)
except NotLoggedInException:
return redirect(about)
notes = mastodon.notifications(limit=100, max_id=next, since_id=prev)
try:
prev = notes[0]._pagination_prev
if len(mastodon.notifications(since_id=prev['since_id'])) == 0:
prev = None
except (IndexError, AttributeError):
prev = None
try:
next = notes[-1]._pagination_next
except (IndexError, AttributeError):
next = None
return render(request, 'main/notifications.html',
{'notes': notes,'timeline': 'Notifications',
'timeline_name': 'Notifications',
'own_acct': request.session['user'],
'preferences': account.preferences,
'prev': prev, 'next': next})
@br_login_required
def thread(request, id):
account, mastodon = get_usercontext(request)
context = mastodon.status_context(id)
toot = mastodon.status(id)
return render(request, 'main/thread.html',
{'context': context, 'toot': toot,
'own_acct': request.session['user'],
'preferences': account.preferences})
@br_login_required
def user(request, username, prev=None, next=None):
try:
account, mastodon = get_usercontext(request)
except NotLoggedInException:
return redirect(about)
try:
user_dict = mastodon.account_search(username)[0]
except (IndexError, AttributeError):
raise Http404("The user %s could not be found." % username)
data = mastodon.account_statuses(user_dict.id, max_id=next, since_id=prev)
relationship = mastodon.account_relationships(user_dict.id)[0]
try:
prev = data[0]._pagination_prev
if len(mastodon.account_statuses(user_dict.id,
since_id=prev['since_id'])) == 0:
prev = None
except (IndexError, AttributeError):
prev = None
try:
next = data[-1]._pagination_next
except (IndexError, AttributeError):
next = None
return render(request, 'main/user.html',
{'toots': data, 'user': user_dict,
'relationship': relationship,
'own_acct': request.session['user'],
'preferences': account.preferences,
'prev': prev, 'next': next})
@never_cache
@br_login_required
def settings(request):
account = Account.objects.get(username=request.session['username'])
if request.method == 'POST':
form = PreferencesForm(request.POST)
if form.is_valid():
account.preferences.theme =form.cleaned_data['theme']
account.preferences.filter_replies = form.cleaned_data['filter_replies']
account.preferences.filter_boosts = form.cleaned_data['filter_boosts']
account.preferences.timezone = form.cleaned_data['timezone']
request.session['timezone'] = account.preferences.timezone
account.preferences.save()
account.save()
return redirect(home)
else:
return render(request, 'setup/settings.html',
{'form' : form, 'account': account})
else:
request.session['timezone'] = account.preferences.timezone
form = PreferencesForm(instance=account.preferences)
return render(request, 'setup/settings.html',
{ 'form': form,
'account': account,
'preferences': account.preferences})
@never_cache
@br_login_required
def toot(request, mention=None):
account, mastodon = get_usercontext(request)
if request.method == 'GET':
if mention:
if not mention.startswith('@'):
mention = '@'+mention
form = PostForm(initial={'visibility': request.session['user'].source.privacy,
'status': mention + '\n' })
else:
form = PostForm(initial={'visibility': request.session['user'].source.privacy})
return render(request, 'main/post.html',
{'form': form,
'own_acct': request.session['user'],
'preferences': account.preferences})
elif request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
# create media objects
media_objects = []
for index in range(1,5):
if 'media_file_'+str(index) in request.FILES:
media_objects.append(
mastodon.media_post(request.FILES['media_file_'+str(index)]
.temporary_file_path(),
description=request.POST.get('media_text_'
+str(index),
None)))
if form.cleaned_data['visibility'] == '':
form.cleaned_data['visibility'] = request.session['user'].source.privacy
mastodon.status_post(status=form.cleaned_data['status'],
visibility=form.cleaned_data['visibility'],
spoiler_text=form.cleaned_data['spoiler_text'],
media_ids=media_objects)
return redirect(home)
else:
return render(request, 'main/post.html',
{'form': form,
'own_acct': request.session['user'],
'preferences': account.preferences})
else:
return redirect(toot)
@br_login_required
def redraft(request, id):
if request.method == 'GET':
account, mastodon = get_usercontext(request)
toot = mastodon.status(id)
toot_content = BeautifulSoup(toot.content).get_text("\n")
form = PostForm({'status': toot_content,
'visibility': toot.visibility,
'spoiler_text': toot.spoiler_text,
'media_text_1': safe_get_attachment(toot, 0).description,
'media_text_2': safe_get_attachment(toot, 1).description,
'media_text_3': safe_get_attachment(toot, 2).description,
'media_text_4': safe_get_attachment(toot, 3).description,
})
return render(request, 'main/redraft.html',
{'toot': toot, 'form': form, 'redraft':True,
'own_acct': request.session['user'],
'preferences': account.preferences})
elif request.method == 'POST':
form = PostForm(request.POST, request.FILES)
account, mastodon = get_usercontext(request)
toot = mastodon.status(id)
if form.is_valid():
media_objects = []
for index in range(1,5):
if 'media_file_'+str(index) in request.FILES:
media_objects.append(
mastodon.media_post(request.FILES['media_file_'+str(index)]
.temporary_file_path(),
description=request.POST.get('media_text_'
+str(index),
None)))
if form.cleaned_data['visibility'] == '':
form.cleaned_data['visibility'] = request.session['user'].source.privacy
mastodon.status_post(status=form.cleaned_data['status'],
visibility=form.cleaned_data['visibility'],
spoiler_text=form.cleaned_data['spoiler_text'],
media_ids=media_objects,
in_reply_to_id=toot.in_reply_to_id)
mastodon.status_delete(id)
return redirect(home)
else:
return render(request, 'main/redraft.html',
{'toot': toot, 'form': form, 'redraft': True,
'own_acct': request.session['user'],
'preferences': account.preferences})
else:
return redirect(redraft, id)
def safe_get_attachment(toot, index):
"""Get an attachment from a toot, without crashing if it isn't there."""
try:
return toot.media_attachments[index]
except IndexError:
adict = AttribAccessDict()
adict.id, adict.type, adict.description = "", "unknown", ""
adict.url, adict.remote_url, adict.preview_url = '', '', ''
adict.text_url = ''
return adict
@br_login_required
def reply(request, id):
if request.method == 'GET':
account, mastodon = get_usercontext(request)
toot = mastodon.status(id)
context = mastodon.status_context(id)
if toot.account.acct != request.session['user'].acct:
initial_text = '@' + toot.account.acct + " "
else:
initial_text = ""
for mention in [x for x in toot.mentions if x.acct != request.session['user'].acct]:
initial_text +=('@' + mention.acct + " ")
if initial_text != "":
initial_text += "\n"
form = PostForm({'status': initial_text,
'visibility': toot.visibility,
'spoiler_text': toot.spoiler_text})
return render(request, 'main/reply.html',
{'context': context, 'toot': toot, 'form': form, 'reply':True,
'own_acct': request.session['user'],
'preferences': account.preferences})
elif request.method == 'POST':
form = PostForm(request.POST, request.FILES)
account, mastodon = get_usercontext(request)
if form.is_valid():
# create media objects
media_objects = []
for index in range(1,5):
if 'media_file_'+str(index) in request.FILES:
media_objects.append(
mastodon.media_post(request.FILES['media_file_'+str(index)]
.temporary_file_path(),
description=request.POST.get('media_text_'
+str(index),
None)))
mastodon.status_post(status=form.cleaned_data['status'],
visibility=form.cleaned_data['visibility'],
spoiler_text=form.cleaned_data['spoiler_text'],
media_ids=media_objects,
in_reply_to_id=id)
return redirect(thread, id)
else:
toot = mastodon.status(id)
context = mastodon.status_context(id)
return render(request, 'main/reply.html',
{'context': context, 'toot': toot, 'form': form, 'reply': True,
'own_acct': request.session['user'],
'preferences': account.preferences})
else:
return redirect(reply, id)
@never_cache
@br_login_required
def fav(request, id):
account, mastodon = get_usercontext(request)
toot = mastodon.status(id)
if request.method == 'POST':
if not request.POST.get('cancel', None):
if toot.favourited:
mastodon.status_unfavourite(id)
else:
mastodon.status_favourite(id)
return redirect(thread, id)
else:
return render(request, 'main/fav.html',
{"toot": toot,
'own_acct': request.session['user'],
"confirm_page": True,
'preferences': account.preferences})
@never_cache
@br_login_required
def boost(request, id):
account, mastodon = get_usercontext(request)
toot = mastodon.status(id)
if request.method == 'POST':
if not request.POST.get('cancel', None):
if toot.reblogged:
mastodon.status_unreblog(id)
else:
mastodon.status_reblog(id)
return redirect(thread, id)
else:
return render(request, 'main/boost.html',
{"toot": toot,
'own_acct': request.session['user'],
'confirm_page': True,
"preferences": account.preferences})
@never_cache
@br_login_required
def delete(request, id):
account, mastodon = get_usercontext(request)
toot = mastodon.status(id)
if request.method == 'POST':
if toot.account.acct != request.session['user'].acct:
return redirect('home')
if not request.POST.get('cancel', None):
mastodon.status_delete(id)
return redirect(home)
else:
return render(request, 'main/delete.html',
{"toot": toot,
'own_acct': request.session['user'],
'confirm_page': True,
"preferences": account.preferences})
@never_cache
@br_login_required
def follow(request, id):
account, mastodon = get_usercontext(request)
try:
user_dict = mastodon.account(id)
relationship = mastodon.account_relationships(user_dict.id)[0]
except (IndexError, AttributeError):
raise Http404("The user could not be found.")
if request.method == 'POST':
if not request.POST.get('cancel', None):
if relationship.requested or relationship.following:
mastodon.account_unfollow(id)
else:
mastodon.account_follow(id)
return redirect(user, user_dict.acct)
else:
return render(request, 'main/follow.html',
{"user": user_dict, "relationship": relationship,
"confirm_page": True,
'own_acct': request.session['user'],
'preferences': account.preferences})
@never_cache
@br_login_required
def block(request, id):
account, mastodon = get_usercontext(request)
try:
user_dict = mastodon.account(id)
relationship = mastodon.account_relationships(user_dict.id)[0]
except (IndexError, AttributeError):
raise Http404("The user could not be found.")
if request.method == 'POST':
if not request.POST.get('cancel', None):
if relationship.blocking:
mastodon.account_unblock(id)
else:
mastodon.account_block(id)
return redirect(user, user_dict.acct)
else:
return render(request, 'main/block.html',
{"user": user_dict, "relationship": relationship,
"confirm_page": True,
'own_acct': request.session['user'],
'preferences': account.preferences})
@never_cache
@br_login_required
def mute(request, id):
account, mastodon = get_usercontext(request)
try:
user_dict = mastodon.account(id)
relationship = mastodon.account_relationships(user_dict.id)[0]
except (IndexError, AttributeError):
raise Http404("The user could not be found.")
if request.method == 'POST':
if not request.POST.get('cancel', None):
if relationship.muting:
mastodon.account_unmute(id)
else:
mastodon.account_mute(id)
return redirect(user, user_dict.acct)
else:
return render(request, 'main/mute.html',
{"user": user_dict, "relationship": relationship,
"confirm_page": True,
'own_acct': request.session['user'],
'preferences': account.preferences})
@br_login_required
def search(request):
account, mastodon = get_usercontext(request)
return render(request, 'main/search.html',
{"preferences": account.preferences,
'own_acct': request.session['user'],
})
@br_login_required
def search_results(request):
if request.method == 'GET':
query = request.GET.get('q', '')
elif request.method == 'POST':
query = request.POST.get('q', '')
else:
query = ''
account, mastodon = get_usercontext(request)
results = mastodon.search(query)
return render(request, 'main/search_results.html',
{"results": results,
'own_acct': request.session['user'],
"preferences": account.preferences})
def about(request):
version = django_settings.BRUTALDON_VERSION
account, mastodon = get_usercontext(request)
if account:
preferences = account.preferences
else:
preferences = None
return render(request, 'about.html',
{"preferences": preferences,
"version": version,
'own_acct': request.session.get('user', None),
})
def privacy(request):
account, mastodon = get_usercontext(request)
return render(request, 'privacy.html',
{"preferences": preferences,
'own_acct' : request.session.get('user', None)})
@cache_page(60 * 30)
@br_login_required
def emoji_reference(request):
account, mastodon = get_usercontext(request)
emojos = mastodon.custom_emojis()
return render(request, 'main/emoji.html',
{"preferences": account.preferences,
"emojos": sorted(emojos, key=lambda x: x['shortcode']),
'own_acct' : request.session['user']})