Reformat everything with black

This commit is contained in:
Jason McBrayer 2019-05-17 13:07:11 -04:00
parent 82404c98b6
commit 5443b41c0e
30 changed files with 3351 additions and 1021 deletions

View File

@ -5,69 +5,91 @@ from pytz import common_timezones
from .models import Theme, Preference from .models import Theme, Preference
PRIVACY_CHOICES = (('public', _('Public')), PRIVACY_CHOICES = (
('unlisted', _('Unlisted')), ("public", _("Public")),
('private', _('Private')), ("unlisted", _("Unlisted")),
('direct', _('Direct'))) ("private", _("Private")),
("direct", _("Direct")),
)
timezones = [(tz, tz) for tz in common_timezones]
timezones = [ (tz, tz) for tz in common_timezones]
class LoginForm(forms.Form): class LoginForm(forms.Form):
instance = forms.CharField(label=_("Instance"), instance = forms.CharField(label=_("Instance"), max_length=256)
max_length=256)
email = forms.EmailField(label=_("Email")) email = forms.EmailField(label=_("Email"))
password = forms.CharField(widget=forms.PasswordInput()) password = forms.CharField(widget=forms.PasswordInput())
class OAuthLoginForm(forms.Form): class OAuthLoginForm(forms.Form):
instance = forms.CharField(label=_("Instance"), instance = forms.CharField(label=_("Instance"), max_length=256)
max_length=256)
class PreferencesForm(forms.ModelForm): class PreferencesForm(forms.ModelForm):
class Meta: class Meta:
model = Preference model = Preference
fields = ['theme', 'filter_replies', 'filter_boosts', 'timezone', fields = [
'no_javascript', 'notifications', 'click_to_load', 'lightbox', "theme",
'filter_notifications', 'poll_frequency'] "filter_replies",
"filter_boosts",
"timezone",
"no_javascript",
"notifications",
"click_to_load",
"lightbox",
"filter_notifications",
"poll_frequency",
]
class PostForm(forms.Form): class PostForm(forms.Form):
"""def status_post(self, status, in_reply_to_id=None, media_ids=None, """def status_post(self, status, in_reply_to_id=None, media_ids=None,
sensitive=False, visibility=None, spoiler_text=None):""" sensitive=False, visibility=None, spoiler_text=None):"""
status = forms.CharField(label="Toot", widget=forms.Textarea) status = forms.CharField(label="Toot", widget=forms.Textarea)
visibility = forms.ChoiceField(label=_("Toot visibility"), choices=PRIVACY_CHOICES, visibility = forms.ChoiceField(
required=False) label=_("Toot visibility"), choices=PRIVACY_CHOICES, required=False
spoiler_text = forms.CharField(label=_("CW or Subject"), )
required=False) spoiler_text = forms.CharField(label=_("CW or Subject"), required=False)
media_file_1 = forms.FileField(label = _("Media 1"), media_file_1 = forms.FileField(label=_("Media 1"), required=False)
required=False) media_text_1 = forms.CharField(label=_("Describe media 1."), required=False)
media_text_1 = forms.CharField(label=_("Describe media 1."), media_file_2 = forms.FileField(label=_("Media 2"), required=False)
required=False) media_text_2 = forms.CharField(label=_("Describe media 2."), required=False)
media_file_2 = forms.FileField(label = _("Media 2"), media_file_3 = forms.FileField(label=_("Media 3"), required=False)
required=False) media_text_3 = forms.CharField(label=_("Describe media 3."), required=False)
media_text_2 = forms.CharField(label=_("Describe media 2."), media_file_4 = forms.FileField(label=_("Media 4"), required=False)
required=False) media_text_4 = forms.CharField(label=_("Describe media 4."), required=False)
media_file_3 = forms.FileField(label = _("Media 3"),
required=False)
media_text_3 = forms.CharField(label=_("Describe media 3."),
required=False)
media_file_4 = forms.FileField(label = _("Media 4"),
required=False)
media_text_4 = forms.CharField(label=_("Describe media 4."),
required=False)
media_sensitive = forms.BooleanField(label=_("Sensitive media?"), required=False) media_sensitive = forms.BooleanField(label=_("Sensitive media?"), required=False)
class FilterForm(forms.Form): class FilterForm(forms.Form):
phrase = forms.CharField(label=_("Word or phrase to filter")) phrase = forms.CharField(label=_("Word or phrase to filter"))
context_home = forms.BooleanField(label=_("In home timeline"), required=False, initial=True) context_home = forms.BooleanField(
context_public = forms.BooleanField(label=_("In public timelines"), required=False, initial=True) label=_("In home timeline"), required=False, initial=True
context_notes = forms.BooleanField(label=_("In notifications"), required=False, initial=True) )
context_thread = forms.BooleanField(label=_("In thread contexts"), required=False, initial=True) context_public = forms.BooleanField(
whole_word = forms.BooleanField(label=_("Whole words only"), required=False, initial=True) label=_("In public timelines"), required=False, initial=True
expires_in = forms.TypedChoiceField(label=_("Expires in"), )
choices=(("", "Never"), context_notes = forms.BooleanField(
("1800", "30 minutes"), label=_("In notifications"), required=False, initial=True
("3600", "1 hour"), )
("21600", "6 hours"), context_thread = forms.BooleanField(
("43200", "12 hours"), label=_("In thread contexts"), required=False, initial=True
("86400", "1 day"), )
("604800", "1 week")), whole_word = forms.BooleanField(
coerce=int, required=False) label=_("Whole words only"), required=False, initial=True
)
expires_in = forms.TypedChoiceField(
label=_("Expires in"),
choices=(
("", "Never"),
("1800", "30 minutes"),
("3600", "1 hour"),
("21600", "6 hours"),
("43200", "12 hours"),
("86400", "1 day"),
("604800", "1 week"),
),
coerce=int,
required=False,
)

View File

@ -3,9 +3,10 @@ import pytz
from django.utils import timezone from django.utils import timezone
from django.utils.deprecation import MiddlewareMixin from django.utils.deprecation import MiddlewareMixin
class TimezoneMiddleware(MiddlewareMixin): class TimezoneMiddleware(MiddlewareMixin):
def process_request(self, request): def process_request(self, request):
tzname = request.session.get('timezone', "UTC") tzname = request.session.get("timezone", "UTC")
if tzname: if tzname:
timezone.activate(pytz.timezone(tzname)) timezone.activate(pytz.timezone(tzname))
else: else:

View File

@ -7,18 +7,25 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = []
]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='Client', name="Client",
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('name', models.TextField(default='brutaldon')), "id",
('api_base_id', models.URLField(default='mastodon.social')), models.AutoField(
('client_id', models.TextField(blank=True, null=True)), auto_created=True,
('client_secret', models.TextField(blank=True, null=True)), primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.TextField(default="brutaldon")),
("api_base_id", models.URLField(default="mastodon.social")),
("client_id", models.TextField(blank=True, null=True)),
("client_secret", models.TextField(blank=True, null=True)),
], ],
), )
] ]

View File

@ -9,17 +9,32 @@ class Migration(migrations.Migration):
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('brutaldon', '0001_initial'), ("brutaldon", "0001_initial"),
] ]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='Account', name="Account",
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('username', models.CharField(max_length=80)), "id",
('access_token', models.TextField(blank=True, null=True)), models.AutoField(
('django_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("username", models.CharField(max_length=80)),
("access_token", models.TextField(blank=True, null=True)),
(
"django_user",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
], ],
), )
] ]

View File

@ -6,19 +6,21 @@ import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0002_account")]
('brutaldon', '0002_account'),
]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='account', model_name="account",
name='client', name="client",
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='brutaldon.Client'), field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="brutaldon.Client",
),
), ),
migrations.AlterField( migrations.AlterField(
model_name='client', model_name="client",
name='api_base_id', name="api_base_id",
field=models.URLField(default='https://mastodon.social'), field=models.URLField(default="https://mastodon.social"),
), ),
] ]

View File

@ -5,14 +5,12 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0003_auto_20180424_1255")]
('brutaldon', '0003_auto_20180424_1255'),
]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='account', model_name="account",
name='username', name="username",
field=models.EmailField(max_length=254), field=models.EmailField(max_length=254),
), )
] ]

View File

@ -6,37 +6,62 @@ import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0004_auto_20180424_1424")]
('brutaldon', '0004_auto_20180424_1424'),
]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='Preference', name="Preference",
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('data_saver', models.BooleanField(default=False)), "id",
('fix_emojos', models.BooleanField(default=False)), models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("data_saver", models.BooleanField(default=False)),
("fix_emojos", models.BooleanField(default=False)),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
name='Theme', name="Theme",
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), (
('name', models.TextField(max_length=80)), "id",
('main_css', models.TextField(max_length=1024)), models.AutoField(
('tweaks_css', models.TextField(blank=True, max_length=1024, null=True)), auto_created=True,
('is_brutalist', models.BooleanField(default=False)), primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.TextField(max_length=80)),
("main_css", models.TextField(max_length=1024)),
(
"tweaks_css",
models.TextField(blank=True, max_length=1024, null=True),
),
("is_brutalist", models.BooleanField(default=False)),
], ],
), ),
migrations.AddField( migrations.AddField(
model_name='preference', model_name="preference",
name='theme', name="theme",
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='brutaldon.Theme'), field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="brutaldon.Theme",
),
), ),
migrations.AddField( migrations.AddField(
model_name='account', model_name="account",
name='preferences', name="preferences",
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='brutaldon.Preference'), field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="brutaldon.Preference",
),
), ),
] ]

View File

@ -5,14 +5,14 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0005_auto_20180618_2103")]
('brutaldon', '0005_auto_20180618_2103'),
]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='theme', model_name="theme",
name='main_css', name="main_css",
field=models.TextField(blank=True, default='css/fullbrutalism.css', max_length=1024, null=True), field=models.TextField(
), blank=True, default="css/fullbrutalism.css", max_length=1024, null=True
),
)
] ]

View File

@ -2,67 +2,80 @@
from django.db import migrations from django.db import migrations
def set_up_default_themes(apps, schema_editor): def set_up_default_themes(apps, schema_editor):
Theme = apps.get_model('brutaldon', 'Theme') Theme = apps.get_model("brutaldon", "Theme")
default = Theme(name="default", default = Theme(
main_css="css/bulma.min.css", name="default",
tweaks_css="css/brutaldon.css", main_css="css/bulma.min.css",
is_brutalist=False) tweaks_css="css/brutaldon.css",
is_brutalist=False,
)
default.save() default.save()
dark = Theme(name="default dark", dark = Theme(
main_css="css/bulmaswatch-darkly.min.css", name="default dark",
tweaks_css="css/brutaldon-dark.css", main_css="css/bulmaswatch-darkly.min.css",
is_brutalist=False) tweaks_css="css/brutaldon-dark.css",
is_brutalist=False,
)
dark.save() dark.save()
lux = Theme(name="Lux", lux = Theme(
main_css="css/bulmaswatch-lux.min.css", name="Lux",
tweaks_css="css/brutaldon.css", main_css="css/bulmaswatch-lux.min.css",
is_brutalist=False) tweaks_css="css/brutaldon.css",
is_brutalist=False,
)
lux.save() lux.save()
solar = Theme(name="Solar", solar = Theme(
main_css="css/bulmaswatch-solar.min.css", name="Solar",
tweaks_css="css/brutaldon.css", main_css="css/bulmaswatch-solar.min.css",
is_brutalist=False) tweaks_css="css/brutaldon.css",
is_brutalist=False,
)
solar.save() solar.save()
brutalism = Theme(name="FULLBRUTALISM", brutalism = Theme(
main_css="css/fullbrutalism.css", name="FULLBRUTALISM", main_css="css/fullbrutalism.css", is_brutalist=True
is_brutalist=True) )
brutalism.save() brutalism.save()
brutstrap = Theme(name="Brutstrap", brutstrap = Theme(
main_css="css/brutstrap.css", name="Brutstrap",
is_brutalist=True, main_css="css/brutstrap.css",
tweaks_css="css/brutstrap-tweaks.css") is_brutalist=True,
tweaks_css="css/brutstrap-tweaks.css",
)
brutstrap.save() brutstrap.save()
large = Theme(name="Minimalist Large", main_css="css/minimal-large.css", large = Theme(
is_brutalist=True) name="Minimalist Large", main_css="css/minimal-large.css", is_brutalist=True
)
large.save() large.save()
small = Theme(name="Minimalist Small", main_css="css/minimal-small.css", small = Theme(
is_brutalist=True) name="Minimalist Small", main_css="css/minimal-small.css", is_brutalist=True
)
small.save() small.save()
dark2 = Theme(name="Minimalist Dark", main_css="css/minimal-dark.css", dark2 = Theme(
is_brutalist=True) name="Minimalist Dark", main_css="css/minimal-dark.css", is_brutalist=True
)
dark2.save() dark2.save()
vt240 = Theme(name="vt240 amber", main_css="css/vt240don-amber.css", vt240 = Theme(
is_brutalist=True) name="vt240 amber", main_css="css/vt240don-amber.css", is_brutalist=True
)
vt240.save() vt240.save()
vt240_green = Theme(name="vt240 green", main_css="css/vt240don-green.css", vt240_green = Theme(
is_brutalist=True) name="vt240 green", main_css="css/vt240don-green.css", is_brutalist=True
)
vt240_green.save() vt240_green.save()
minimal = Theme(name="No styling at all", main_css=None, is_brutalist=True) minimal = Theme(name="No styling at all", main_css=None, is_brutalist=True)
minimal.save() minimal.save()
def delete_themes(apps, schema_editor): def delete_themes(apps, schema_editor):
Theme = apps.get_model('brutaldon' 'Theme') Theme = apps.get_model("brutaldon" "Theme")
for theme in Theme.objects.all(): for theme in Theme.objects.all():
theme.delete() theme.delete()
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0006_auto_20180618_2112")]
('brutaldon', '0006_auto_20180618_2112'),
]
operations = [ operations = [migrations.RunPython(set_up_default_themes, delete_themes)]
migrations.RunPython(set_up_default_themes, delete_themes)
]

View File

@ -5,14 +5,12 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0007_auto_20180618_2115")]
('brutaldon', '0007_auto_20180618_2115'),
]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='theme', model_name="theme",
name='name', name="name",
field=models.TextField(max_length=80, unique=True), field=models.TextField(max_length=80, unique=True),
), )
] ]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,14 +5,12 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0011_auto_20180825_1017")]
('brutaldon', '0011_auto_20180825_1017'),
]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='account', model_name="account",
name='username', name="username",
field=models.EmailField(max_length=254, unique=True), field=models.EmailField(max_length=254, unique=True),
), )
] ]

View File

@ -6,14 +6,16 @@ import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0012_auto_20180826_1853")]
('brutaldon', '0012_auto_20180826_1853'),
]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='preference', model_name="preference",
name='theme', name="theme",
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='brutaldon.Theme'), field=models.ForeignKey(
), default=1,
on_delete=django.db.models.deletion.CASCADE,
to="brutaldon.Theme",
),
)
] ]

View File

@ -5,14 +5,10 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0013_auto_20180826_1935")]
('brutaldon', '0013_auto_20180826_1935'),
]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='account', model_name="account", name="note_seen", field=models.IntegerField(null=True)
name='note_seen', )
field=models.IntegerField(null=True),
),
] ]

View File

@ -5,24 +5,22 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0014_account_note_seen")]
('brutaldon', '0014_account_note_seen'),
]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='preference', model_name="preference",
name='click_to_load', name="click_to_load",
field=models.BooleanField(default=False), field=models.BooleanField(default=False),
), ),
migrations.AddField( migrations.AddField(
model_name='preference', model_name="preference",
name='no_javascript', name="no_javascript",
field=models.BooleanField(default=False), field=models.BooleanField(default=False),
), ),
migrations.AddField( migrations.AddField(
model_name='preference', model_name="preference",
name='notifications', name="notifications",
field=models.BooleanField(default=True), field=models.BooleanField(default=True),
), ),
] ]

View File

@ -5,29 +5,37 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0015_auto_20181001_1812")]
('brutaldon', '0015_auto_20181001_1812'),
]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='preference', model_name="preference",
name='lightbox', name="lightbox",
field=models.BooleanField(default=False, help_text='Use a JavaScript lightbox to display media.'), field=models.BooleanField(
default=False, help_text="Use a JavaScript lightbox to display media."
),
), ),
migrations.AlterField( migrations.AlterField(
model_name='preference', model_name="preference",
name='click_to_load', name="click_to_load",
field=models.BooleanField(default=False, help_text='Click to load more toots in the same page, rather than using pagination.'), field=models.BooleanField(
default=False,
help_text="Click to load more toots in the same page, rather than using pagination.",
),
), ),
migrations.AlterField( migrations.AlterField(
model_name='preference', model_name="preference",
name='no_javascript', name="no_javascript",
field=models.BooleanField(default=False, help_text='Disable all JavaScript. Overrides all other JavaScript options.'), field=models.BooleanField(
default=False,
help_text="Disable all JavaScript. Overrides all other JavaScript options.",
),
), ),
migrations.AlterField( migrations.AlterField(
model_name='preference', model_name="preference",
name='notifications', name="notifications",
field=models.BooleanField(default=True, help_text='Display live notifications in header.'), field=models.BooleanField(
default=True, help_text="Display live notifications in header."
),
), ),
] ]

View File

@ -5,14 +5,15 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0016_auto_20181009_1805")]
('brutaldon', '0016_auto_20181009_1805'),
]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='preference', model_name="preference",
name='poll_frequency', name="poll_frequency",
field=models.IntegerField(default=300, help_text='Number of seconds to wait between checking notifications. Default: 300'), field=models.IntegerField(
), default=300,
help_text="Number of seconds to wait between checking notifications. Default: 300",
),
)
] ]

View File

@ -5,14 +5,15 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0017_preference_poll_frequency")]
('brutaldon', '0017_preference_poll_frequency'),
]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='preference', model_name="preference",
name='filter_notifications', name="filter_notifications",
field=models.BooleanField(default=False, help_text='Exclude boosts and favs from your notifications.'), field=models.BooleanField(
), default=False,
help_text="Exclude boosts and favs from your notifications.",
),
)
] ]

File diff suppressed because one or more lines are too long

View File

@ -5,14 +5,12 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0019_auto_20190124_0813")]
('brutaldon', '0019_auto_20190124_0813'),
]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='account', model_name="account",
name='note_seen', name="note_seen",
field=models.CharField(blank=True, max_length=128, null=True), field=models.CharField(blank=True, max_length=128, null=True),
), )
] ]

View File

@ -5,14 +5,12 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0020_auto_20190127_2159")]
('brutaldon', '0020_auto_20190127_2159'),
]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='client', model_name="client",
name='version', name="version",
field=models.CharField(default='1.0', max_length=8), field=models.CharField(default="1.0", max_length=8),
), )
] ]

View File

@ -5,14 +5,12 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("brutaldon", "0021_client_version")]
('brutaldon', '0021_client_version'),
]
operations = [ operations = [
migrations.AlterField( migrations.AlterField(
model_name='client', model_name="client",
name='version', name="version",
field=models.CharField(default='1.0', max_length=80), field=models.CharField(default="1.0", max_length=80),
), )
] ]

View File

@ -5,8 +5,9 @@ from pytz import common_timezones
timezones = [(tz, tz) for tz in common_timezones] timezones = [(tz, tz) for tz in common_timezones]
class Client(models.Model): class Client(models.Model):
name = models.CharField(default = "brutaldon", max_length=80) name = models.CharField(default="brutaldon", max_length=80)
api_base_id = models.URLField(default="https://mastodon.social") api_base_id = models.URLField(default="https://mastodon.social")
version = models.CharField(default="1.0", max_length=80) version = models.CharField(default="1.0", max_length=80)
client_id = models.CharField(null=True, blank=True, max_length=2048) client_id = models.CharField(null=True, blank=True, max_length=2048)
@ -15,42 +16,62 @@ class Client(models.Model):
def __str__(self): def __str__(self):
return self.name + ": " + self.api_base_id return self.name + ": " + self.api_base_id
class Theme(models.Model): class Theme(models.Model):
name = models.CharField(max_length=80, unique=True) name = models.CharField(max_length=80, unique=True)
prefix = models.CharField(max_length=40, null=True, default="default") prefix = models.CharField(max_length=40, null=True, default="default")
main_css = models.CharField(max_length=1024, blank=True, null=True, main_css = models.CharField(
default="css/fullbrutalism.css") max_length=1024, blank=True, null=True, default="css/fullbrutalism.css"
)
tweaks_css = models.CharField(max_length=1024, blank=True, null=True) tweaks_css = models.CharField(max_length=1024, blank=True, null=True)
is_brutalist = models.BooleanField(default=False) is_brutalist = models.BooleanField(default=False)
def __str__(self): def __str__(self):
return self.name return self.name
class Preference(models.Model): class Preference(models.Model):
theme = models.ForeignKey(Theme, models.CASCADE, null=False, default=1) theme = models.ForeignKey(Theme, models.CASCADE, null=False, default=1)
filter_replies = models.BooleanField(default=False) filter_replies = models.BooleanField(default=False)
filter_boosts = models.BooleanField(default=False) filter_boosts = models.BooleanField(default=False)
timezone = models.CharField(max_length=80, blank=True, null=True, timezone = models.CharField(
choices=timezones, default='UTC') max_length=80, blank=True, null=True, choices=timezones, default="UTC"
no_javascript = models.BooleanField(default=False, )
help_text=_("""Disable all JavaScript. Overrides all other JavaScript options.""")) no_javascript = models.BooleanField(
notifications = models.BooleanField(default=True, default=False,
help_text=_("""Display live notifications in header.""")) help_text=_(
click_to_load = models.BooleanField(default=False, """Disable all JavaScript. Overrides all other JavaScript options."""
help_text=_("""Click to load more toots in the same page, rather than using pagination.""")) ),
lightbox = models.BooleanField(default=False, )
help_text=_("""Use a JavaScript lightbox to display media.""")) notifications = models.BooleanField(
poll_frequency = models.IntegerField(default=300, default=True, help_text=_("""Display live notifications in header.""")
help_text=_("""Number of seconds to wait between checking notifications. Default: 300""")) )
filter_notifications = models.BooleanField(default=False, click_to_load = models.BooleanField(
help_text=_("""Exclude boosts and favs from your notifications.""")) default=False,
help_text=_(
"""Click to load more toots in the same page, rather than using pagination."""
),
)
lightbox = models.BooleanField(
default=False, help_text=_("""Use a JavaScript lightbox to display media.""")
)
poll_frequency = models.IntegerField(
default=300,
help_text=_(
"""Number of seconds to wait between checking notifications. Default: 300"""
),
)
filter_notifications = models.BooleanField(
default=False,
help_text=_("""Exclude boosts and favs from your notifications."""),
)
class Account(models.Model): class Account(models.Model):
username = models.EmailField(unique=True) username = models.EmailField(unique=True)
email = models.EmailField(null=True, blank=True) email = models.EmailField(null=True, blank=True)
django_user = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE, null=True) django_user = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE, null=True)
access_token = models.CharField(null=True, blank=True, max_length=2048) access_token = models.CharField(null=True, blank=True, max_length=2048)
client= models.ForeignKey(Client, models.SET_NULL, null=True) client = models.ForeignKey(Client, models.SET_NULL, null=True)
preferences = models.ForeignKey(Preference, models.SET_NULL, null=True) preferences = models.ForeignKey(Preference, models.SET_NULL, null=True)
note_seen = models.CharField(null=True, blank=True, max_length=128) note_seen = models.CharField(null=True, blank=True, max_length=128)

View File

@ -20,7 +20,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '6lq9!52j^)=m89))umaphx9ac%)b$k^gs%x1rkk^v^$u9zjz$@' SECRET_KEY = "6lq9!52j^)=m89))umaphx9ac%)b$k^gs%x1rkk^v^$u9zjz$@"
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
@ -31,57 +31,57 @@ ALLOWED_HOSTS = []
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
'django.contrib.admin', "django.contrib.admin",
'django.contrib.auth', "django.contrib.auth",
'django.contrib.contenttypes', "django.contrib.contenttypes",
'django.contrib.sessions', "django.contrib.sessions",
'django.contrib.messages', "django.contrib.messages",
'django.contrib.staticfiles', "django.contrib.staticfiles",
'widget_tweaks', "widget_tweaks",
'sanitizer', "sanitizer",
'django.contrib.humanize', "django.contrib.humanize",
'brutaldon', "brutaldon",
] ]
MIDDLEWARE = [ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', "django.middleware.security.SecurityMiddleware",
'django.contrib.sessions.middleware.SessionMiddleware', "django.contrib.sessions.middleware.SessionMiddleware",
'django.middleware.common.CommonMiddleware', "django.middleware.common.CommonMiddleware",
'django.middleware.csrf.CsrfViewMiddleware', "django.middleware.csrf.CsrfViewMiddleware",
'django.contrib.auth.middleware.AuthenticationMiddleware', "django.contrib.auth.middleware.AuthenticationMiddleware",
'django.contrib.messages.middleware.MessageMiddleware', "django.contrib.messages.middleware.MessageMiddleware",
'django.middleware.clickjacking.XFrameOptionsMiddleware', "django.middleware.clickjacking.XFrameOptionsMiddleware",
'brutaldon.middleware.timezone.TimezoneMiddleware', "brutaldon.middleware.timezone.TimezoneMiddleware",
] ]
ROOT_URLCONF = 'brutaldon.urls' ROOT_URLCONF = "brutaldon.urls"
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', "BACKEND": "django.template.backends.django.DjangoTemplates",
'DIRS': [], "DIRS": [],
'APP_DIRS': True, "APP_DIRS": True,
'OPTIONS': { "OPTIONS": {
'context_processors': [ "context_processors": [
'django.template.context_processors.debug', "django.template.context_processors.debug",
'django.template.context_processors.request', "django.template.context_processors.request",
'django.contrib.auth.context_processors.auth', "django.contrib.auth.context_processors.auth",
'django.contrib.messages.context_processors.messages', "django.contrib.messages.context_processors.messages",
], ]
}, },
}, }
] ]
WSGI_APPLICATION = 'brutaldon.wsgi.application' WSGI_APPLICATION = "brutaldon.wsgi.application"
# Database # Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
DATABASES = { DATABASES = {
'default': { "default": {
'ENGINE': 'django.db.backends.sqlite3', "ENGINE": "django.db.backends.sqlite3",
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), "NAME": os.path.join(BASE_DIR, "db.sqlite3"),
} }
} }
@ -91,78 +91,68 @@ DATABASES = {
AUTH_PASSWORD_VALIDATORS = [ AUTH_PASSWORD_VALIDATORS = [
{ {
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
}, },
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
] ]
LOGGING = { LOGGING = {
'version': 1, "version": 1,
'disable_existing_loggers': False, "disable_existing_loggers": False,
'filters': { "filters": {
'require_debug_false': { "require_debug_false": {"()": "django.utils.log.RequireDebugFalse"},
'()': 'django.utils.log.RequireDebugFalse', "require_debug_true": {"()": "django.utils.log.RequireDebugTrue"},
}, },
'require_debug_true': { "formatters": {
'()': 'django.utils.log.RequireDebugTrue', "django.server": {
}, "()": "django.utils.log.ServerFormatter",
}, "format": "[%(server_time)s] %(message)s",
'formatters': { }
'django.server': { },
'()': 'django.utils.log.ServerFormatter', "handlers": {
'format': '[%(server_time)s] %(message)s', "console": {
} "level": "INFO",
}, "filters": ["require_debug_true"],
'handlers': { "class": "logging.StreamHandler",
'console': { },
'level': 'INFO', "console_debug_false": {
'filters': ['require_debug_true'], "level": "ERROR",
'class': 'logging.StreamHandler', "filters": ["require_debug_false"],
}, "class": "logging.StreamHandler",
'console_debug_false': { },
'level': 'ERROR', "django.server": {
'filters': ['require_debug_false'], "level": "INFO",
'class': 'logging.StreamHandler', "class": "logging.StreamHandler",
}, "formatter": "django.server",
'django.server': { },
'level': 'INFO', "mail_admins": {
'class': 'logging.StreamHandler', "level": "ERROR",
'formatter': 'django.server', "filters": ["require_debug_false"],
}, "class": "django.utils.log.AdminEmailHandler",
'mail_admins': { },
'level': 'ERROR', },
'filters': ['require_debug_false'], "loggers": {
'class': 'django.utils.log.AdminEmailHandler' "django": {
} "handlers": ["console", "console_debug_false", "mail_admins"],
}, "level": "INFO",
'loggers': { },
'django': { "django.server": {
'handlers': ['console', 'console_debug_false', 'mail_admins'], "handlers": ["django.server"],
'level': 'INFO', "level": "INFO",
}, "propagate": False,
'django.server': { },
'handlers': ['django.server'], },
'level': 'INFO',
'propagate': False,
}
}
} }
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/ # https://docs.djangoproject.com/en/2.0/topics/i18n/
LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = "en-us"
TIME_ZONE = 'America/New_York' TIME_ZONE = "America/New_York"
USE_I18N = True USE_I18N = True
@ -174,13 +164,29 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/ # https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_URL = '/static/' STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, 'static') STATIC_ROOT = os.path.join(BASE_DIR, "static")
# Sanitizer settings # Sanitizer settings
SANITIZER_ALLOWED_TAGS = ['a', 'p', 'img', 'br', 'i', 'strong', 'em', 'pre', 'code', SANITIZER_ALLOWED_TAGS = [
'ul', 'li', 'ol', 'blockquote', 'del', 'span', 'u'] "a",
SANITIZER_ALLOWED_ATTRIBUTES = ['href', 'src', 'title', 'alt', 'class', 'lang'] "p",
"img",
"br",
"i",
"strong",
"em",
"pre",
"code",
"ul",
"li",
"ol",
"blockquote",
"del",
"span",
"u",
]
SANITIZER_ALLOWED_ATTRIBUTES = ["href", "src", "title", "alt", "class", "lang"]
# File upload settings. # File upload settings.
# Important: media will not work if you change this. # Important: media will not work if you change this.
@ -188,11 +194,10 @@ FILE_UPLOAD_HANDLERS = ["django.core.files.uploadhandler.TemporaryFileUploadHand
# Session serialization # Session serialization
# Important: whatever you choose has to be able to serialize DateTime, so not JSON. # Important: whatever you choose has to be able to serialize DateTime, so not JSON.
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' SESSION_SERIALIZER = "django.contrib.sessions.serializers.PickleSerializer"
# URL to redirect users to when not logged in # URL to redirect users to when not logged in
ANONYMOUS_HOME_URL = 'about' ANONYMOUS_HOME_URL = "about"
# Version number displayed on about page # Version number displayed on about page
BRUTALDON_VERSION = "2.12.1" BRUTALDON_VERSION = "2.12.1"

View File

@ -6,9 +6,10 @@ from django import template
register = template.Library() register = template.Library()
@register.filter(is_safe=True) @register.filter(is_safe=True)
def humane_time(arg): def humane_time(arg):
'''Returns a time string that is humane but not relative (unlike Django's humanetime) """Returns a time string that is humane but not relative (unlike Django's humanetime)
For times less than 6 hours ago: display date and time to the minute. For times less than 6 hours ago: display date and time to the minute.
For times less than 12 hours ago: display date and time to the hour. For times less than 12 hours ago: display date and time to the hour.
@ -27,7 +28,7 @@ def humane_time(arg):
FIXME: work out how best to make these strings translatable FIXME: work out how best to make these strings translatable
''' """
now = django_now() now = django_now()
arg = localtime(arg) arg = localtime(arg)
diff = now - arg diff = now - arg
@ -42,13 +43,14 @@ def humane_time(arg):
return arg.strftime("%a, %b %d, %Y around %I %p") + utc return arg.strftime("%a, %b %d, %Y around %I %p") + utc
elif diff < timedelta(hours=36): elif diff < timedelta(hours=36):
return arg.strftime("%a, %b %d, %Y in the ") + time_of_day(arg.hour) + utc return arg.strftime("%a, %b %d, %Y in the ") + time_of_day(arg.hour) + utc
elif diff < timedelta(days=6*28): elif diff < timedelta(days=6 * 28):
return arg.strftime("%b %d, %Y") return arg.strftime("%b %d, %Y")
elif diff < timedelta(days=10*365): elif diff < timedelta(days=10 * 365):
return arg.strftime("%b, %Y") return arg.strftime("%b, %Y")
else: else:
return arg.strftime("%Y") return arg.strftime("%Y")
def time_of_day(hour): def time_of_day(hour):
"""Return a description of what time of day an hour is. """Return a description of what time of day an hour is.

View File

@ -7,79 +7,88 @@ from pdb import set_trace
register = template.Library() register = template.Library()
@register.filter @register.filter
def pdb(element): def pdb(element):
set_trace() set_trace()
return element return element
@register.filter @register.filter
def relink_tags(value): def relink_tags(value):
'''Treat the text as html, and replace tag links with app-internal tag links """Treat the text as html, and replace tag links with app-internal tag links
Currently, this only works for tags in toots coming from Mastodon servers, Currently, this only works for tags in toots coming from Mastodon servers,
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 links FIXME: handle arbitrary tag links
''' """
value = value.replace('&apos;', "'") value = value.replace("&apos;", "'")
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"):
try: try:
link['href'] = reverse('tag', args=[link.span.string]) link["href"] = reverse("tag", args=[link.span.string])
except: except:
continue continue
return soup.decode(formatter='html') return soup.decode(formatter="html")
@register.filter @register.filter
def relink_mentions(value): def relink_mentions(value):
'''Treat the text as html, and replace mention links with app-internal links """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, Currently, this only works for mentions in toots coming from Mastodon servers,
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 mentions. it relies on the markup that Mastodon puts on mentions.
FIXME: handle arbitrary mention links FIXME: handle arbitrary mention links
''' """
value = value.replace('&apos;', "'") value = value.replace("&apos;", "'")
soup = BeautifulSoup(value, 'html.parser') soup = BeautifulSoup(value, "html.parser")
for link in soup.find_all('a', class_='mention'): for link in soup.find_all("a", class_="mention"):
parsed = parse.urlparse(link['href']) parsed = parse.urlparse(link["href"])
try: try:
instance = parsed[1] instance = parsed[1]
user = parsed[2][2:] user = parsed[2][2:]
link['href'] = reverse('user', args=[user+'@'+instance]) link["href"] = reverse("user", args=[user + "@" + instance])
except: except:
continue continue
return soup.decode(formatter='html') return soup.decode(formatter="html")
@register.filter @register.filter
def relink_toot(value): def relink_toot(value):
return relink_tags(relink_mentions(value)) return relink_tags(relink_mentions(value))
@register.filter @register.filter
def localuser(value): def localuser(value):
'''Convert a remote user link to local''' """Convert a remote user link to local"""
try: try:
parsed = parse.urlparse(value) parsed = parse.urlparse(value)
instance = parsed[1] instance = parsed[1]
if parsed[2].startswith('/@'): if parsed[2].startswith("/@"):
user = parsed[2][2:] user = parsed[2][2:]
else: else:
user = parsed[2].split('/')[-1] user = parsed[2].split("/")[-1]
local = reverse('user', args=[user+'@'+instance]) local = reverse("user", args=[user + "@" + instance])
except: except:
local = value local = value
return local return local
@register.filter @register.filter
def fix_emojos(value, emojos): def fix_emojos(value, emojos):
'''Replace instances of recognized custom emoji :shortcodes: in value with image link tags """Replace instances of recognized custom emoji :shortcodes: in value with image link tags
''' """
for emojo in emojos: for emojo in emojos:
try: try:
value = value.replace(":%(shortcode)s:" % emojo, value = value.replace(
'<img src="%(url)s" title=":%(shortcode)s:" alt=":%(shortcode)s:" class="emoji">' % emojo) ":%(shortcode)s:" % emojo,
'<img src="%(url)s" title=":%(shortcode)s:" alt=":%(shortcode)s:" class="emoji">'
% emojo,
)
except: except:
continue continue
return value return value

View File

@ -18,55 +18,55 @@ from django.urls import path
from brutaldon import views from brutaldon import views
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), path("admin/", admin.site.urls),
path('about', views.about, name='about'), path("about", views.about, name="about"),
path('privacy', views.privacy, name='privacy'), path("privacy", views.privacy, name="privacy"),
path('home/next/<next>', views.home, name='home_next'), path("home/next/<next>", views.home, name="home_next"),
path('home/prev/<prev>', views.home, name='home_prev'), path("home/prev/<prev>", views.home, name="home_prev"),
path('home', views.home, name='home'), path("home", views.home, name="home"),
path('login', views.login, name="login"), path("login", views.login, name="login"),
path('oldlogin', views.old_login, name="oldlogin"), path("oldlogin", views.old_login, name="oldlogin"),
path('logout', views.logout, name='logout'), path("logout", views.logout, name="logout"),
path('oauth_callback', views.oauth_callback, name="oauth_callback"), path("oauth_callback", views.oauth_callback, name="oauth_callback"),
path('error', views.error, name='error'), path("error", views.error, name="error"),
path('local', views.local, name='local'), path("local", views.local, name="local"),
path('local/next/<next>', views.local, name='local_next'), path("local/next/<next>", views.local, name="local_next"),
path('local/prev/<prev>', views.local, name='local_prev'), path("local/prev/<prev>", views.local, name="local_prev"),
path('fed', views.fed, name='fed'), path("fed", views.fed, name="fed"),
path('fed/next/<next>', views.fed, name='fed_next'), path("fed/next/<next>", views.fed, name="fed_next"),
path('fed/prev/<prev>', views.fed, name='fed_prev'), path("fed/prev/<prev>", views.fed, name="fed_prev"),
path('note', views.note, name='note'), path("note", views.note, name="note"),
path('note/next<next>', views.note, name='note_next'), path("note/next<next>", views.note, name="note_next"),
path('note/prev/<prev>', views.note, name='note_prev'), path("note/prev/<prev>", views.note, name="note_prev"),
path('notes_count', views.notes_count, name='notes_count'), path("notes_count", views.notes_count, name="notes_count"),
path('user_search', views.user_search, name='user_search'), path("user_search", views.user_search, name="user_search"),
path('settings', views.settings, name='settings'), path("settings", views.settings, name="settings"),
path('thread/<id>', views.thread, name='thread'), path("thread/<id>", views.thread, name="thread"),
path('tags/<tag>', views.tag, name='tag'), path("tags/<tag>", views.tag, name="tag"),
path('user/', views.home, name='user_bad'), path("user/", views.home, name="user_bad"),
path('user/<username>', views.user, name='user'), path("user/<username>", views.user, name="user"),
path('user/<username>/next/<int:next>', views.user, name='user_next'), path("user/<username>/next/<int:next>", views.user, name="user_next"),
path('user/<username>/prev/<int:prev>', views.user, name='user_prev'), path("user/<username>/prev/<int:prev>", views.user, name="user_prev"),
path('toot/<mention>', views.toot, name='toot'), path("toot/<mention>", views.toot, name="toot"),
path('toot', views.toot, name="toot"), path("toot", views.toot, name="toot"),
path('reply/<id>', views.reply, name='reply'), path("reply/<id>", views.reply, name="reply"),
path('redraft/<id>', views.redraft, name='redraft'), path("redraft/<id>", views.redraft, name="redraft"),
path('fav/<id>', views.fav, name='fav'), path("fav/<id>", views.fav, name="fav"),
path('boost/<id>', views.boost, name='boost'), path("boost/<id>", views.boost, name="boost"),
path('delete/<id>', views.delete, name='delete'), path("delete/<id>", views.delete, name="delete"),
path('follow/<id>', views.follow, name='follow'), path("follow/<id>", views.follow, name="follow"),
path('block/<id>', views.block, name='block'), path("block/<id>", views.block, name="block"),
path('mute/<id>', views.mute, name='mute'), path("mute/<id>", views.mute, name="mute"),
path('search', views.search, name='search'), path("search", views.search, name="search"),
path('search_results', views.search_results, name='search_results'), path("search_results", views.search_results, name="search_results"),
path('emoji', views.emoji_reference, name='emoji'), path("emoji", views.emoji_reference, name="emoji"),
path('filters/list', views.list_filters, name='list_filters'), path("filters/list", views.list_filters, name="list_filters"),
path('filters/create', views.create_filter, name='create_filter'), path("filters/create", views.create_filter, name="create_filter"),
path('filters/delete/<id>', views.delete_filter, name='delete_filter'), path("filters/delete/<id>", views.delete_filter, name="delete_filter"),
path('filters/edit/<id>', views.edit_filter, name='edit_filter'), path("filters/edit/<id>", views.edit_filter, name="edit_filter"),
path('requests/', views.follow_requests, name='follow_requests'), path("requests/", views.follow_requests, name="follow_requests"),
path('requests/<id>', views.follow_requests, name='follow_requests'), path("requests/<id>", views.follow_requests, name="follow_requests"),
path('accounts/', views.accounts, name='accounts'), path("accounts/", views.accounts, name="accounts"),
path('accounts/<id>', views.accounts, name='accounts'), path("accounts/<id>", views.accounts, name="accounts"),
path('', views.home, name=''), path("", views.home, name=""),
] ]

File diff suppressed because it is too large Load Diff