mirror of
				https://gitlab.com/brutaldon/brutaldon
				synced 2025-06-05 21:49:32 +02:00 
			
		
		
		
	Support user timelines.
Other user stuff (profile info, follows/followers) and operations on users (follow, block, report) are not added, but relatively easy.
This commit is contained in:
		| @@ -5,12 +5,16 @@ | |||||||
| <article class="media"> | <article class="media"> | ||||||
|     <figure class="media-left"> |     <figure class="media-left"> | ||||||
|         <p class="image is-64x64"> |         <p class="image is-64x64"> | ||||||
|             <img src="{{ toot.account.avatar }}" |             <a href="{% url "user" toot.account.acct %}"> | ||||||
|                  alt=""> |                 <img src="{{ toot.account.avatar }}" | ||||||
|  |                      alt=""> | ||||||
|  |             </a> | ||||||
|         </p> |         </p> | ||||||
|         {% if reblog %} |         {% if reblog %} | ||||||
|             <p class="image is-32x32 reblog-icon" > |             <p class="image is-32x32 reblog-icon" > | ||||||
|                 <img src ="{{ reblog_icon }}" alt=""> |                 <a href="{% url "user" reblog_by %}"> | ||||||
|  |                     <img src ="{{ reblog_icon }}" alt=""> | ||||||
|  |                 </a> | ||||||
|             </p> |             </p> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|     </figure> |     </figure> | ||||||
| @@ -18,7 +22,7 @@ | |||||||
|         <div class="content"> |         <div class="content"> | ||||||
|             <p> |             <p> | ||||||
|                 <strong>{{ toot.account.display_name }}</strong> |                 <strong>{{ toot.account.display_name }}</strong> | ||||||
|                 <small>@{{ toot.account.acct }}</small> |                 <small><a href="{% url "user" toot.account.acct %}">@{{ toot.account.acct }}</a></small> | ||||||
|                 <a href="{{ toot.url }}"> |                 <a href="{{ toot.url }}"> | ||||||
|                     <small>{{ toot.created_at |naturaltime  }}</small> |                     <small>{{ toot.created_at |naturaltime  }}</small> | ||||||
|                 </a> |                 </a> | ||||||
|   | |||||||
							
								
								
									
										44
									
								
								brutaldon/templates/main/user.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								brutaldon/templates/main/user.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | {% extends "base.html" %} | ||||||
|  | {% load humanize %} | ||||||
|  |  | ||||||
|  | {% block title %} | ||||||
|  |     Brutaldon - {{ timeline }} timelime | ||||||
|  | {% endblock %} | ||||||
|  |  | ||||||
|  | {% block content %} | ||||||
|  |  | ||||||
|  |     <h1 class="title">User information for {{ user.display_name }} (@{{ user.acct }})</h1> | ||||||
|  |     <div class="box"> | ||||||
|  |         <p>FIXME</p> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <h1 class="title">{{ user.display_name }}'s visible toots</h1> | ||||||
|  |     {% for toot in toots %} | ||||||
|  |         <div class="box"> | ||||||
|  |             {% if toot.reblog %} | ||||||
|  |                 {% include "main/toot_partial.html" with toot=toot.reblog reblog=True reblog_by=toot.account.acct reblog_icon=toot.account.avatar %} | ||||||
|  |             {% else %} | ||||||
|  |                 {% include "main/toot_partial.html" with toot=toot reblog=False %} | ||||||
|  |             {% endif %} | ||||||
|  |         </div> | ||||||
|  |         <hr class="is-hidden"> | ||||||
|  |     {% endfor %} | ||||||
|  |  | ||||||
|  |     <nav class="pagination" role="navigation" aria-label="pagination"> | ||||||
|  |         <a class="pagination-previous" | ||||||
|  |            title="This is the first page" disabled>Previous</a> | ||||||
|  |         <a class="pagination-next">Next page</a> | ||||||
|  |         <ul class="pagination-list"> | ||||||
|  |             <li> | ||||||
|  |                 <a class="pagination-link is-current" aria-label="Page 1" | ||||||
|  |                    aria-current="page">1</a> | ||||||
|  |             </li> | ||||||
|  |             <li> | ||||||
|  |                 <a class="pagination-link" aria-label="Goto page 2">2</a> | ||||||
|  |             </li> | ||||||
|  |             <li> | ||||||
|  |                 <a class="pagination-link" aria-label="Goto page 3">3</a> | ||||||
|  |             </li> | ||||||
|  |         </ul> | ||||||
|  |     </nav> | ||||||
|  | {% endblock %} | ||||||
| @@ -13,13 +13,34 @@ def relink_tags(value): | |||||||
|     not necessarily GNU Social, Pleroma, or other fediverse servers, because |     not necessarily GNU Social, Pleroma, or other fediverse servers, because | ||||||
|     it relies on the markup that Mastodon puts on tags. |     it relies on the markup that Mastodon puts on tags. | ||||||
|  |  | ||||||
|     FIXME: handle arbitrary tag lengths. |     FIXME: handle arbitrary tag links | ||||||
|     ''' |     ''' | ||||||
|     soup = BeautifulSoup(value, 'html.parser') |     soup = BeautifulSoup(value, 'html.parser') | ||||||
|     for link in soup.find_all('a', class_='hashtag'): |     for link in soup.find_all('a', class_='hashtag'): | ||||||
|         link['href'] = reverse('tag', args=[link.span.string]) |         link['href'] = reverse('tag', args=[link.span.string]) | ||||||
|     return soup.decode(formatter=None) |     return soup.decode(formatter=None) | ||||||
|  |  | ||||||
|  | @register.filter | ||||||
|  | def relink_mentions(value): | ||||||
|  |     '''Treat the text as html, and replace mention links with app-internal links | ||||||
|  |  | ||||||
|  |     Currently, this only works for mentions in toots coming from Mastodon servers, | ||||||
|  |     not necessarily GNU Social, Pleroma, or other fediverse servers, because | ||||||
|  |     it relies on the markup that Mastodon puts on mentions. | ||||||
|  |  | ||||||
|  |     FIXME: handle arbitrary mention links | ||||||
|  |     ''' | ||||||
|  |     soup = BeautifulSoup(value, 'html.parser') | ||||||
|  |     for link in soup.find_all('a', class_='mention'): | ||||||
|  |         parsed = parse.urlparse(link['href']) | ||||||
|  |         try: | ||||||
|  |             instance = parsed[1] | ||||||
|  |             user = parsed[2][2:] | ||||||
|  |             link['href'] = reverse('user', args=[user+'@'+instance]) | ||||||
|  |         except: | ||||||
|  |             continue | ||||||
|  |     return soup.decode(formatter=None) | ||||||
|  |  | ||||||
| @register.filter | @register.filter | ||||||
| def relink_toot(value): | def relink_toot(value): | ||||||
|     return relink_tags(value) |     return relink_tags(relink_mentions(value)) | ||||||
|   | |||||||
| @@ -29,6 +29,7 @@ urlpatterns = [ | |||||||
|     path('settings', views.settings, name='settings'), |     path('settings', views.settings, name='settings'), | ||||||
|     path('thread/<int:id>', views.thread, name='thread'), |     path('thread/<int:id>', views.thread, name='thread'), | ||||||
|     path('tags/<tag>', views.tag, name='tag'), |     path('tags/<tag>', views.tag, name='tag'), | ||||||
|  |     path('user/<username>', views.user, name='user'), | ||||||
|     path('toot', views.toot, name="toot"), |     path('toot', views.toot, name="toot"), | ||||||
|     path('reply/<int:id>', views.reply, name='reply'), |     path('reply/<int:id>', views.reply, name='reply'), | ||||||
|     path('fav/<int:id>', views.fav, name='fav'), |     path('fav/<int:id>', views.fav, name='fav'), | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| from django.http import HttpResponse | from django.http import HttpResponse, Http404 | ||||||
| from django.shortcuts import render, redirect | from django.shortcuts import render, redirect | ||||||
| from django.views.decorators.cache import never_cache | from django.views.decorators.cache import never_cache | ||||||
| from brutaldon.forms import LoginForm, SettingsForm, PostForm | from brutaldon.forms import LoginForm, SettingsForm, PostForm | ||||||
| @@ -48,19 +48,15 @@ def timeline(request, timeline='home', timeline_name='Home'): | |||||||
|                   {'toots': data, 'form': form, 'timeline': timeline_name, |                   {'toots': data, 'form': form, 'timeline': timeline_name, | ||||||
|                    'fullbrutalism': fullbrutalism_p(request)}) |                    'fullbrutalism': fullbrutalism_p(request)}) | ||||||
|  |  | ||||||
| @never_cache |  | ||||||
| def home(request): | def home(request): | ||||||
|     return timeline(request, 'home', 'Home') |     return timeline(request, 'home', 'Home') | ||||||
|  |  | ||||||
| @never_cache |  | ||||||
| def local(request): | def local(request): | ||||||
|     return timeline(request, 'local', 'Local') |     return timeline(request, 'local', 'Local') | ||||||
|  |  | ||||||
| @never_cache |  | ||||||
| def fed(request): | def fed(request): | ||||||
|     return timeline(request, 'public', 'Federated') |     return timeline(request, 'public', 'Federated') | ||||||
|  |  | ||||||
| @never_cache |  | ||||||
| def tag(request, tag): | def tag(request, tag): | ||||||
|     try: |     try: | ||||||
|         mastodon = get_mastodon(request) |         mastodon = get_mastodon(request) | ||||||
| @@ -71,7 +67,7 @@ def tag(request, tag): | |||||||
|                   {'toots': data, 'timeline': '#'+tag, |                   {'toots': data, 'timeline': '#'+tag, | ||||||
|                    'fullbrutalism': fullbrutalism_p(request)}) |                    'fullbrutalism': fullbrutalism_p(request)}) | ||||||
|  |  | ||||||
|  | @never_cache | ||||||
| def login(request): | def login(request): | ||||||
|     if request.method == "GET": |     if request.method == "GET": | ||||||
|         form = LoginForm() |         form = LoginForm() | ||||||
| @@ -129,6 +125,7 @@ def login(request): | |||||||
|         else: |         else: | ||||||
|             return render(request, 'setup/login.html', {'form': form}) |             return render(request, 'setup/login.html', {'form': form}) | ||||||
|  |  | ||||||
|  | @never_cache | ||||||
| def logout(request): | def logout(request): | ||||||
|     request.session.flush() |     request.session.flush() | ||||||
|     return redirect(home) |     return redirect(home) | ||||||
| @@ -136,7 +133,6 @@ def logout(request): | |||||||
| def error(request): | def error(request): | ||||||
|     return render(request, 'error.html', { 'error': "Not logged in yet."}) |     return render(request, 'error.html', { 'error': "Not logged in yet."}) | ||||||
|  |  | ||||||
| @never_cache |  | ||||||
| def note(request): | def note(request): | ||||||
|     mastodon = get_mastodon(request) |     mastodon = get_mastodon(request) | ||||||
|     notes = mastodon.notifications() |     notes = mastodon.notifications() | ||||||
| @@ -144,7 +140,6 @@ def note(request): | |||||||
|                   {'notes': notes,'timeline': 'Notifications', |                   {'notes': notes,'timeline': 'Notifications', | ||||||
|                    'fullbrutalism': fullbrutalism_p(request)}) |                    'fullbrutalism': fullbrutalism_p(request)}) | ||||||
|  |  | ||||||
| @never_cache |  | ||||||
| def thread(request, id): | def thread(request, id): | ||||||
|     mastodon = get_mastodon(request) |     mastodon = get_mastodon(request) | ||||||
|     context = mastodon.status_context(id) |     context = mastodon.status_context(id) | ||||||
| @@ -153,6 +148,18 @@ def thread(request, id): | |||||||
|                   {'context': context, 'toot': toot, |                   {'context': context, 'toot': toot, | ||||||
|                    'fullbrutalism': fullbrutalism_p(request)}) |                    'fullbrutalism': fullbrutalism_p(request)}) | ||||||
|  |  | ||||||
|  | def user(request, username): | ||||||
|  |     mastodon = get_mastodon(request) | ||||||
|  |     try: | ||||||
|  |         user_dict = mastodon.account_search(username)[0] | ||||||
|  |     except IndexError: | ||||||
|  |         raise Http404("The user %s could not be found." % username) | ||||||
|  |     data = mastodon.account_statuses(user_dict.id) | ||||||
|  |     return render(request, 'main/user.html', | ||||||
|  |                   {'toots': data, 'user': user_dict, | ||||||
|  |                    'fullbrutalism': fullbrutalism_p(request)}) | ||||||
|  |  | ||||||
|  |  | ||||||
| @never_cache | @never_cache | ||||||
| def settings(request): | def settings(request): | ||||||
|     if request.method == 'POST': |     if request.method == 'POST': | ||||||
| @@ -202,7 +209,6 @@ def toot(request): | |||||||
|     else: |     else: | ||||||
|         return redirect(toot) |         return redirect(toot) | ||||||
|  |  | ||||||
| @never_cache |  | ||||||
| def reply(request, id): | def reply(request, id): | ||||||
|     if request.method == 'GET': |     if request.method == 'GET': | ||||||
|         mastodon = get_mastodon(request) |         mastodon = get_mastodon(request) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user