- Merge with closedverse-video-support
- user_tools moved to forms.py
- community_tools moved to forms.py
This commit is contained in:
some weird guy
2023-08-19 17:17:00 -07:00
parent 49477bf178
commit 1b33a2aad1
50 changed files with 660 additions and 439 deletions
+13 -1
View File
@@ -2,15 +2,27 @@ Stuff that is done:
- Disable comments button
- merge with closedverse-video-support (mostly)
- Prevent users from posting in communities created by blocked users.
<<<<<<< Updated upstream
=======
- Hide email password reset form if no SMTP server is set up. (done by Arian Kordi)
- Fix icon and banner uploads.
Icons and banners use util.image_upload now, at the cost of having to set them all again.
>>>>>>> Stashed changes
Stuff that is in progress
- Removing shitty code.
- Finding and killing bugs!
- moving to forms.py
Stuff that I want
- Image and video file boxes in one.
- Pinning posts????
Not needed at all if I'm being honest.
- Ways for mods to view who invited who.
<<<<<<< Updated upstream
- Hide email password reset form if no SMTP server is set up.
- Fix icon and banner uploads. Make that shit work with image_upload
=======
- Full ImageField integration
- remove the useless feedback thing. (You can just make a bug reporting community)
>>>>>>> Stashed changes
+30 -2
View File
@@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
from django.conf.global_settings import PASSWORD_HASHERS
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -129,7 +130,9 @@ LOGGING = {
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
# only use these when debug is not enabled so that making dummy accounts in debug is easier
if not DEBUG:
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
@@ -142,8 +145,13 @@ AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
]
# append the old passlib hasher to the end of PASSWORD_HASHERS
# you only need this if your closedverse instance has passwords from before 08/2023, otherwise leave it commented
# although django has a bcrypt sha256 method, it's not compatible with passlib's, which is what closedverse used
# python3 -m pip install django-hashers-passlib
#PASSWORD_HASHERS += ['hashers_passlib.bcrypt_sha256']
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
@@ -160,6 +168,14 @@ USE_L10N = False
USE_TZ = True
# You can use Mailtrap to get the email system working. Mailtrap is free and will work well for what you'll be doing with this.
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = None
EMAIL_HOST_USER = None
EMAIL_HOST_PASSWORD = None
EMAIL_PORT = None
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = None
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
@@ -239,6 +255,7 @@ DISALLOW_PROXY = False
# Setting this to True forces every user to log in/
# sign up for the site to view any content.
FORCE_LOGIN = False
# A list of URLs that are always accessible
# whether the above value is set or not.
LOGIN_EXEMPT_URLS = {
@@ -249,6 +266,7 @@ LOGIN_EXEMPT_URLS = {
r'^help/rules$',
r'^help/contact$',
r'^help/login$',
r'^s/.*$',
}
# Action to perform on images belonging to posts/
@@ -272,6 +290,7 @@ level_needed_to_man_communities = 5
# if someone's level is equal or above this, they can edit any user with a lower level on your clone.
level_needed_to_man_users = 5
<<<<<<< Updated upstream
# file size limits in megabytes! only applies when using the community tools.
max_icon_size = .5
max_banner_size = 1
@@ -280,6 +299,8 @@ max_banner_size = 1
# This will definitely miss a few people off who just want to sign up without worrying about long passwords.
minimum_password_length = 7
=======
>>>>>>> Stashed changes
# The hard limit for uploading, Will cause an error if this is exceeded. This is set to 15MB by default (15728640)
DATA_UPLOAD_MAX_MEMORY_SIZE = 52428800
@@ -297,6 +318,13 @@ age_allowed = "13"
# brand name currently being implemented throughout templates
brand_name = "Cedar"
memo_title = 'Cedar-Django'
memo_msg = """
<h2>Cedar</h2>
<p>what</p>
<h2>Why is this person rehosting it?</h2>
<p>im bored</p>"""
# This option enables some production-specific pages
# and routines, such as HTTPS scheme redirection and
# proxy detection via IPHub.
+17 -5
View File
@@ -126,11 +126,6 @@ class AdsAdmin(admin.ModelAdmin):
class InvitesAdmin(admin.ModelAdmin):
raw_id_fileds = ('id', 'created', 'creator')
class WelcomemsgAdmin(admin.ModelAdmin):
raw_id_fileds = ('id', 'created', 'message', )
list_display = ('Title', 'message', 'show', 'order', 'created', )
actions = [Hide_Memo, Show_Memo]
class YeahAdmin(admin.ModelAdmin):
raw_id_fields = ('by', 'post', 'comment', )
list_display = ('by', 'post', 'comment', )
@@ -140,10 +135,14 @@ class HistoryAdmin(admin.ModelAdmin):
raw_id_fields = ('user',)
list_display = ('id', 'user')
class RoleAdmin(admin.ModelAdmin):
exclude = ('is_static', )
#class BlockAdmin(admin.ModelAdmin)
admin.site.unregister(Group)
admin.site.register(models.Role, RoleAdmin)
admin.site.register(models.User, UserAdmin)
admin.site.register(models.Profile, ProfileAdmin)
admin.site.register(models.Community, CommunityAdmin)
@@ -158,6 +157,7 @@ admin.site.register(models.ProfileHistory, HistoryAdmin)
admin.site.register(models.Post, PostAdmin)
admin.site.register(models.Comment, CommentAdmin)
<<<<<<< Updated upstream
admin.site.register(models.Ads, AdsAdmin)
admin.site.register(models.welcomemsg, WelcomemsgAdmin)
admin.site.register(models.Yeah, YeahAdmin)
@@ -167,3 +167,15 @@ admin.site.register(models.Friendship, ConversationAdmin)
admin.site.register(models.Invites, InvitesAdmin)
admin.site.register(models.Poll)
admin.site.register(models.PollVote)
=======
if settings.DEBUG:
admin.site.register(models.Yeah)
admin.site.register(models.Follow)
admin.site.register(models.FriendRequest)
admin.site.register(models.Friendship, ConversationAdmin)
#admin.site.register(models.Notification)
admin.site.register(models.Poll)
admin.site.register(models.PollVote)
admin.site.register(models.Ads, AdsAdmin)
>>>>>>> Stashed changes
+6 -1
View File
@@ -5,8 +5,13 @@ except ImportError:
from closedverse_main import apps
brand_name = apps.ClosedverseMainConfig.verbose_name
# for brand logo
from closedverse.settings import STATIC_URL
# variable for this and name are here for imports
brand_logo = STATIC_URL + 'img/menu-logo.svg'
# the name of the function is merely what's imported into settings.py
def brand_name_universal(request):
# this returns what's actually newly available to the template
# so the name of the key actually dictates what you put in the tmpl
return {"brand_name": brand_name}
return {"brand_name": brand_name, "brand_logo": brand_logo}
+52
View File
@@ -0,0 +1,52 @@
from django import forms
from .models import *
from django.core.exceptions import ValidationError
# I do want to move each and every form over to here. Not only will this trivialize making new forms, this will also make it more secure or something.
class CommunitySettingForm(forms.ModelForm):
community_name = forms.CharField(max_length=64,required=True)
community_description = forms.CharField(max_length = 2200,required=False)
community_platform = forms.IntegerField(max_value = 7, min_value = 0, required = True)
force_login = forms.BooleanField(required = False)
community_icon = forms.ImageField(required = False)
community_banner = forms.ImageField(required = False)
class Meta:
model = Community
fields = (
'community_name',
'community_description',
'community_platform',
'force_login',
'community_icon',
'community_banner'
)
class PurgeForm(forms.Form):
purge_posts = forms.BooleanField(required=False, label='Purge all posts', help_text='Purge all posts from this user.')
purge_comments = forms.BooleanField(required=False, label='Purge all comments', help_text='Purge all comments from this user.')
restore_all = forms.BooleanField(required=False, label='Restore purged content', help_text='Restore everything that was purged, this will not apply to posts deleted manually.')
class UserForm(forms.ModelForm):
username = forms.CharField(max_length = 64, required = True, help_text = 'Usernames are used when signing in, so be sure to let this user know if you change this.')
c_tokens = forms.IntegerField(min_value = 0, max_value = 100, required = False, help_text = 'The remaining C-Tokens this user has.')
has_mh = forms.BooleanField(required = False, label='Use Mii', help_text='Don\'t fuck with this please.')
avatar = forms.CharField(required = False, help_text = 'If \"Use Mii\" is turned on, The Mii ID should reside here, otherwise any good old URL will do.')
class Meta:
model = User
fields = ['username', 'nickname', 'role', 'c_tokens', 'hide_online', 'active', 'can_invite', 'warned', 'has_mh', 'avatar', 'warned_reason']
def clean_username(self):
username = self.cleaned_data.get('username')
if not re.compile(r'^[A-Za-z0-9-._]{1,32}$').match(username) or not re.compile(r'[A-Za-z0-9]').match(username):
raise forms.ValidationError("The username contains invalid characters.")
return username
class ProfileForm(forms.ModelForm):
# applying classes is super weird.
comment = forms.CharField(required=False, widget=forms.Textarea(attrs={'class': 'textarea'}))
let_freedom = forms.BooleanField(required=False, label='Let this user upload images?', help_text='If you disable this, This user will not be able to post images, videos or make a new account.')
class Meta:
model = Profile
fields = ['comment', 'country', 'whatareyou', 'weblink', 'external', 'let_freedom', 'limit_post', 'cannot_edit', 'pronoun_is', 'id_visibility', 'let_friendrequest', 'yeahs_visibility', 'comments_visibility']
-6
View File
@@ -42,12 +42,6 @@ class ClosedMiddleware(object):
# can just forbid post requests for the time being (but leav our funny logout message :3)
if not request.user.is_active() and request.method != 'GET' and request.get_full_path() != '/logout/':
return HttpResponseForbidden()
# If there isn't a request.session
if not request.session.get('passwd'):
request.session['passwd'] = request.user.password
else:
if request.session['passwd'] != request.user.password:
logout(request)
response = self.get_response(request)
if request.user.is_authenticated:
# for reverse proxy
+89 -80
View File
@@ -1,16 +1,16 @@
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import BaseUserManager
from django.db.models import Q, QuerySet, Max, F, Count, Case, When, Exists, OuterRef, Subquery
from django.utils import timezone
from django.forms.models import model_to_dict
from django.utils.dateformat import format
from django.core.validators import RegexValidator, URLValidator
from django.core.exceptions import ValidationError
from datetime import timedelta, datetime, date, time
from passlib.hash import bcrypt_sha256
from datetime import timedelta, time
#from passlib.hash import bcrypt_sha256
# you may want to import django.conf.settings instead (then change checks for DEFAULT_FROM_EMAIL)
from closedverse import settings
from closedverse_main.context_processors import brand_name
from closedverse_main.context_processors import brand_name, brand_logo
from . import util
from random import getrandbits
import uuid, json, base64
@@ -18,7 +18,6 @@ from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.urls import reverse
from django.db.models.signals import pre_delete
from django.dispatch import receiver
import re
import unicodedata
import random
@@ -120,12 +119,23 @@ class ColorField(models.CharField):
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 18
super(ColorField, self).__init__(*args, **kwargs)
# custom role in db
class Role(models.Model):
id = models.AutoField(primary_key=True)
# determines whether to fetch role from static or media, for built-in roles
is_static = models.BooleanField(default=False)
image = models.ImageField(upload_to='roles/', max_length=100, help_text='Upload an icon that will show on the top right of one\'s profile.')
organization = models.CharField(max_length=255, blank=True, null=True, help_text='Text that shows above one\'s username')
def __str__(self):
return "role \"" + str(self.organization) + "\""
#mii_domain = 'https://mii-secure.cdn.nintendo.net'
# as of writing, mii-secure is unstable, nintendo please do not f*ck me for this
mii_domain = 'https://s3.us-east-1.amazonaws.com/mii-images.account.nintendo.net/'
class User(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
class User(AbstractBaseUser):
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=32, unique=True)
# Todo: Don't allow nickname to be null (once this is fixed, un-str-ify line 357 of views; the one with ogdata description)
@@ -139,13 +149,23 @@ class User(models.Model):
# LEVEL: 0-1 is default, everything else is just levels
level = models.SmallIntegerField(default=0)
# ROLE: This doesn't have anything
<<<<<<< Updated upstream
role = models.SmallIntegerField(default=0, choices=((0, 'normal'), (1, 'bot'), (2, 'administrator'), (3, 'moderator'), (4, 'openverse'), (5, 'donator'), (6, 'cool'), (7, 'urapp'), (8, 'owner'), (9, 'badgedes'), (10, 'jack'), (11, 'verified'),))
=======
#role = models.SmallIntegerField(default=0, choices=((0, 'normal'), (1, 'bot'), (2, 'administrator'), (3, 'moderator'), (4, 'openverse'), (5, 'donator'), (6, 'cool'), (7, 'urapp'), (8, 'owner'), (9, 'badgedes'), (10, 'jack'), (11, 'verified'),))
role = models.ForeignKey(Role, blank=True, null=True, on_delete=models.SET_NULL, help_text='This will show a funny badge and text on this user\'s profile. This does not grant the user any additional power and is only visual.')
>>>>>>> Stashed changes
addr = models.CharField(max_length=64, null=True, blank=True)
signup_addr = models.CharField(max_length=64, null=True, blank=True)
user_agent = models.TextField(null=True, blank=True)
# C Tokens are things that let you make communities and shit.
<<<<<<< Updated upstream
c_tokens = models.IntegerField(default=1)
protect_data = models.BooleanField(default=False)
=======
c_tokens = models.IntegerField(default=1, help_text='How many communities should this user be allowed to make?')
protect_data = models.BooleanField(default=False, null=True, help_text='Prevent people from lookin\' at private data for this user.')
>>>>>>> Stashed changes
# Things that don't have to do with auth lol
hide_online = models.BooleanField(default=False)
@@ -189,16 +209,19 @@ class User(models.Model):
return self.warned
def get_warned_reason(self):
return self.warned_reason
"""
def set_password(self, raw_password):
self.password = bcrypt_sha256.using(rounds=13).hash(raw_password)
def check_password(self, raw_password):
return bcrypt_sha256.using(rounds=13).verify(raw_password, hash=self.password)
"""
def profile(self, thing=None):
# If thing is specified, that field is retrieved
if thing:
# could this be shortened? or discontinued in general
return self.profile_set.all().values_list(thing, flat=True).first()
# Otherwise just get full profile
return self.profile_set.filter(user=self).first()
return self.profile_set.filter().first()
def gravatar(self):
g = util.get_gravatar(self.email)
if not g:
@@ -238,34 +261,29 @@ class User(models.Model):
return int(limit) - recent_posts
def get_class(self):
"""
first = {
1: 'cool',
2: 'administrator',
3: 'moderator',
4: 'openverse',
5: 'donator',
6: 'cool',
7: 'urapp',
8: 'developer',
9: 'badgedes',
10: 'jack',
11: 'verifiedd',
1: '/s/img/bot.png',
2: '/s/img/administrator.png',
3: '/s/img/moderator.png',
9: '/s/img/badgedes.png',
}.get(self.role, '')
second = {
1: "Bot",
2: "Administrator",
3: "Moderator",
4: "O-PHP-enverse Man",
5: "Donator",
6: "Cool Person",
7: "cave story is okay",
8: "owner guy",
9: "Badge Designer",
10: "stupid man",
11: "Verified",
}.get(self.role, '')
if first:
first = 'official ' + first
"""
#if first:
# first = 'official ' + first
if not self.role:
return [None, None]
#first = self.role.image
second = self.role.organization
first = self.role.image.url
if self.role.is_static:
first = settings.STATIC_URL + self.role.image.name
return [first, second]
def is_me(self, request):
if request.user.is_authenticated:
@@ -305,17 +323,17 @@ class User(models.Model):
return self.avatar
def num_yeahs(self):
return self.yeah_set.filter(by=self).count()
return self.yeah_set.count()
def num_posts(self):
return self.post_set.filter(creator=self).count()
return self.post_set.count()
def num_comments(self):
return self.comment_set.filter().count()
return self.comment_set.count()
def num_following(self):
return self.follow_source.filter().count()
return self.follow_source.count()
def num_followers(self):
return self.follow_target.filter().count()
return self.follow_target.count()
def num_friends(self):
return self.friend_source.filter().count() + self.friend_target.filter().count()
return self.friend_source.count() + self.friend_target.count()
def can_follow(self, user):
if UserBlock.find_block(self, user):
return False
@@ -345,7 +363,7 @@ class User(models.Model):
return False
return self.follow_target.filter(source=source, target=self).delete()
def can_block(self, source):
if self.can_manage() or self.level > source.level:
if self.can_manage() or self.level > source.level or self == source:
return False
#if source.profile('moyenne'):
# return False
@@ -353,15 +371,21 @@ class User(models.Model):
# BLOCK this user from SOURCE
def make_block(self, source):
# trailing
block = UserBlock.find_block(self, source)
if block and block.source == source:
return block.delete()
if UserBlock.objects.filter(source=source, target=self).exists():
return False
if not self.can_block(source):
return False
fs = Friendship.find_friendship(self, source)
if fs:
fs.delete()
# delete any mutual follows
Follow.objects.filter(Q(source=self) & Q(target=source) | Q(target=self) & Q(source=source)).delete()
return UserBlock.objects.create(source=source, target=self)
def remove_block(self, source):
find_block = UserBlock.objects.filter(source=source, target=self)
if not find_block:
return False
return find_block.delete()
def get_posts(self, limit, offset, request, offset_time):
if request.user.is_authenticated:
has_yeah = Yeah.objects.filter(post=OuterRef('id'), by=request.user.id)
@@ -454,7 +478,12 @@ class User(models.Model):
except:
pass
def send_fr(self, source, body=None):
if not self.get_fr(source):
if self == source or not self.profile().can_friend(source):
return False
if self.get_fr(source):
return False
if Friendship.find_friendship(self, source):
return False
return FriendRequest.objects.create(source=source, target=self, body=body)
def accept_fr(self, target):
fr = self.get_fr(target)
@@ -517,7 +546,7 @@ class User(models.Model):
return self.save(update_fields=['last_login'])
def has_postspam(self, body, screenshot=None, drawing=None):
latest_post = self.post_set.filter().order_by('-created')[:1]
latest_post = self.post_set.order_by('-created')[:1]
if not latest_post:
return False
latest_post = latest_post.first()
@@ -545,7 +574,7 @@ class User(models.Model):
return messages
def password_reset_email(self, request):
htmlmsg = render_to_string('closedverse_main/help/email.html', {
'menulogo': request.build_absolute_uri(settings.STATIC_URL + 'img/menu-logo.svg'),
'menulogo': request.build_absolute_uri(brand_logo),
'contact': request.build_absolute_uri(reverse('main:help-contact')),
'link': request.build_absolute_uri(reverse('main:forgot-passwd')) + "?token=" + base64.urlsafe_b64encode(bytes(self.password, 'utf-8')).decode(),
})
@@ -609,7 +638,6 @@ class Invites(models.Model):
return "invite by " + str(self.creator)
class Community(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
description = models.TextField(blank=True, default='')
@@ -673,6 +701,7 @@ class Community(models.Model):
5: 'pc',
6: 'xbox',
7: 'ps',
8: 'youre-mom',
}.get(self.platform)
if not thing:
return None
@@ -827,7 +856,6 @@ class CommunityFavorite(models.Model):
return "Community favorite by " + str(self.by) + " for " + str(self.community)
class Post(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
id = models.AutoField(primary_key=True)
community = models.ForeignKey(Community, null=True, on_delete=models.CASCADE)
feeling = models.SmallIntegerField(default=0, choices=feelings)
@@ -892,13 +920,13 @@ class Post(models.Model):
def number_yeahs(self):
if hasattr(self, 'num_yeahs'):
return self.num_yeahs
return self.yeah_set.filter(post=self).count()
return self.yeah_set.count()
def has_yeah(self, request):
if request.user.is_authenticated:
if hasattr(self, 'yeah_given'):
return self.yeah_given
else:
return self.yeah_set.filter(post=self, by=request.user).exists()
return self.yeah_set.filter(by=request.user).exists()
else:
return False
def can_yeah(self, request):
@@ -926,14 +954,14 @@ class Post(models.Model):
def remove_yeah(self, request):
if not self.has_yeah(request):
return True
return self.yeah_set.filter(post=self, by=request.user).delete()
return self.yeah_set.filter(by=request.user).delete()
def number_comments(self):
# Number of comments cannot be accurate due to comment deleting
#if hasattr(self, 'num_comments'):
# return self.num_comments
return self.comment_set.filter(original_post=self).count()
return self.comment_set.count()
def get_yeahs(self, request):
return Yeah.objects.filter(type=0, post=self).order_by('-created')[0:30]
return self.yeah_set.order_by('-created')[0:30]
def can_comment(self, request):
if self.number_comments() > 500:
return False
@@ -1105,7 +1133,6 @@ class Post(models.Model):
return the_post.first()
class Comment(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
id = models.AutoField(primary_key=True)
original_post = models.ForeignKey(Post, on_delete=models.CASCADE)
community = models.ForeignKey(Community, on_delete=models.CASCADE)
@@ -1144,13 +1171,13 @@ class Comment(models.Model):
def number_yeahs(self):
if hasattr(self, 'num_yeahs'):
return self.num_yeahs
return self.yeah_set.filter(comment=self, type=1).count()
return self.yeah_set.count()
def has_yeah(self, request):
if request.user.is_authenticated:
if hasattr(self, 'yeah_given'):
return self.yeah_given
else:
return self.yeah_set.filter(comment=self, type=1, by=request.user).exists()
return self.yeah_set.filter(by=request.user).exists()
else:
return False
def can_yeah(self, request):
@@ -1175,7 +1202,7 @@ class Comment(models.Model):
def remove_yeah(self, request):
if not self.has_yeah(request):
return True
return self.yeah_set.filter(comment=self, type=1, by=request.user).delete()
return self.yeah_set.filter(by=request.user).delete()
def get_yeahs(self, request):
return Yeah.objects.filter(type=1, comment=self).order_by('-created')[0:30]
def owner_post(self):
@@ -1219,7 +1246,7 @@ class Comment(models.Model):
self.is_mine = self.is_mine(request.user)
class Yeah(models.Model):
# Todo: make this a plain int at some point
# 2023-08-16: tried to remove this but it is the primary key so it's kind of hard to change
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
by = models.ForeignKey(User, on_delete=models.CASCADE)
type = models.SmallIntegerField(default=0, choices=((0, 'post'), (1, 'comment'), ))
@@ -1232,14 +1259,13 @@ class Yeah(models.Model):
def __str__(self):
a = "from " + self.by.username + " to "
if self.post:
a += str(self.post.unique_id)
a += "post " + str(self.post.id)
elif self.comment:
a += str(self.comment.unique_id)
a += "comment " + str(self.comment.id)
return a
class Profile(models.Model):
is_new = models.BooleanField(default=True)
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
@@ -1272,11 +1298,11 @@ class Profile(models.Model):
# Post limit, 0 for none
limit_post = models.SmallIntegerField(default=0)
# If this is true, the user can't change their avatar or nickname
cannot_edit = models.BooleanField(default=False)
cannot_edit = models.BooleanField(default=False, help_text='Make it so this user cannot change settings.')
email_login = models.SmallIntegerField(default=1, choices=((0, 'Do not allow'), (1, 'Okay'), (2, 'Only allow')))
def __str__(self):
return "profile " + str(self.unique_id) + " for " + self.user.username
return "profile for " + self.user.username
def origin_id_public(self, user=None):
if user == self.user:
return self.origin_id
@@ -1312,12 +1338,12 @@ class Profile(models.Model):
def can_friend(self, user=None):
if self.let_friendrequest == 2:
return False
#if user.is_authenticated and UserBlock.find_block(self.user, user):
# return False
elif self.let_friendrequest == 1:
if not user.is_following(self.user):
return False
return True
if user.is_authenticated and UserBlock.find_block(self.user, user):
return False
return True
def got_fullurl(self):
if self.weblink:
@@ -1342,7 +1368,6 @@ class Profile(models.Model):
class Follow(models.Model):
# Todo: remove this
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
id = models.AutoField(primary_key=True)
source = models.ForeignKey(User, related_name='follow_source', on_delete=models.CASCADE)
target = models.ForeignKey(User, related_name='follow_target', on_delete=models.CASCADE)
@@ -1461,7 +1486,6 @@ class Notification(models.Model):
return user.notification_sender.create(source=user, type=type, to=to, context_post=post, context_comment=comment)
class Complaint(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
id = models.AutoField(primary_key=True)
creator = models.ForeignKey(User, on_delete=models.CASCADE)
type = models.SmallIntegerField(choices=(
@@ -1480,7 +1504,6 @@ class Complaint(models.Model):
return user.complaint_set.filter(created__gt=timezone.now() - timedelta(minutes=5)).exists()
class FriendRequest(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
id = models.AutoField(primary_key=True)
source = models.ForeignKey(User, related_name='fr_source', on_delete=models.CASCADE)
target = models.ForeignKey(User, related_name='fr_target', on_delete=models.CASCADE)
@@ -1496,7 +1519,6 @@ class FriendRequest(models.Model):
self.save()
class Friendship(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
id = models.AutoField(primary_key=True)
source = models.ForeignKey(User, related_name='friend_source', on_delete=models.CASCADE)
target = models.ForeignKey(User, related_name='friend_target', on_delete=models.CASCADE)
@@ -1552,7 +1574,6 @@ class Friendship(models.Model):
return friends
class Conversation(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
id = models.AutoField(primary_key=True)
source = models.ForeignKey(User, related_name='conv_source', on_delete=models.CASCADE)
target = models.ForeignKey(User, related_name='conv_target', on_delete=models.CASCADE)
@@ -1572,9 +1593,9 @@ class Conversation(models.Model):
def set_read(self, user):
return self.unread(user).update(read=True)
def all_read(self):
return self.message_set.filter().update(read=True)
return self.message_set.update(read=True)
def messages(self, request, limit=50, offset=0):
msgs = self.message_set.filter().order_by('-created')[offset:offset + limit]
msgs = self.message_set.order_by('-created')[offset:offset + limit]
for msg in msgs:
msg.mine = msg.mine(request.user)
return msgs
@@ -1601,7 +1622,6 @@ class Conversation(models.Model):
new_post.mine = True
return new_post
class Message(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
id = models.AutoField(primary_key=True)
conversation = models.ForeignKey(Conversation, on_delete=models.CASCADE)
feeling = models.SmallIntegerField(default=0, choices=feelings)
@@ -1660,8 +1680,6 @@ class ConversationInvite(models.Model):
return "Invite to conversation " + str(self.conversation) + " from " + str(self.source) + " to " + str(self.target)
class Poll(models.Model):
# Todo: make this a plain int at some point
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
id = models.AutoField(primary_key=True)
able_vote = models.BooleanField(default=True)
choices = models.TextField(default="[]")
@@ -1812,15 +1830,6 @@ class Ads(models.Model):
def __str__(self):
return "Ad with id " + str(self.id) + ", created at " + str(self.created) + ", with url " + str(self.url) + ", and imageurl " + str(self.imageurl)
class welcomemsg(models.Model):
id = models.AutoField(primary_key=True)
order = models.IntegerField(max_length=3, default=1)
show = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
Title = models.CharField(max_length=256, null=False, blank=False, default='Title')
message = models.TextField(null=False, blank=False)
image = models.ImageField(upload_to='welcomemsg/%y/%m/%d/', max_length=255, null=True, blank=True)
# thing will log changes to your bio or nickname
class ProfileHistory(models.Model):
id = models.AutoField(primary_key=True)
+1 -1
View File
@@ -1,4 +1,4 @@
{% extends "closedverse_main/layout.html" %}
{% load closedverse_tags %}{% block main-body %}
{% nocontent "403 Forbidden" %}
{% nocontent "The page could not be displayed." %}
{% endblock %}
@@ -0,0 +1,43 @@
{% extends "closedverse_main/layout.html" %}
{% load static %}{% load closedverse_user %}{% load closedverse_tags %}
{% block main-body %}
{% user_sidebar request user user.profile 0 True %}
<div class="main-column"><div class="post-list-outline">
<h2 class="label">Blocked Users</h2>
{% if blocks %}
<div class="list news-list" id="friend-list-content">
{% for block in blocks %}
<li class="news-list-content trigger" data-href="{% url "main:user-view" block.target.username %}">
{% user_icon_container block.target %}
<div class="body">
<a href="{% url "main:user-view" block.target.username %}" class="nick-name"{% if block.target.color %}style=color:{{ block.target.color }}{% endif %}>{{ block.target.nickname }}</a><br><span class="timestamp"> {% time block.created %}</span>
<button class="button received-request-button" type="button" dataaa="{{ block.target_id }}">Unblock</button>
</div>
</li>
<div class="dialog none" data-modal-types="post-unblock" id="{{ block.target_id }}">
<div class="dialog-inner">
<div class="window">
<h1 class="window-title">Unblock {{ block.target.nickname }}</h1>
<div class="window-body">
{% user_sidebar_info block.target %}
<form method="post" data-action="{% url "main:user-rmblock" block.target.username %}">
<p class="window-body-content">Unblock this user?</p>
<div class="form-buttons">
<input type="button" class="olv-modal-close-button gray-button" value="No">
<input type="submit" value="Yes" class="post-button black-button">
</div>
</form>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="no-content">
<p>You have not blocked any users.</p>
</div>
{% endif %}
</div></div>
{% endblock %}
@@ -10,7 +10,7 @@
</div>
<div class="post-list-outline more">
<div id="post-content" class="post reply-permalink-post">
<div id="{{ comment.unique_id }}" class="other">
<div class="other">
<p class="community-container"><a {% if comment.community.clickable %}href="{% url "main:community-view" comment.community.id %}"{% endif %}><img src="{{ comment.community.icon }}" class="community-icon">{{ comment.community.name }}</a></p>
{% if comment.is_mine or comment.can_rm %}
{% if user.is_active %}
@@ -34,6 +34,15 @@
</div>
{% endif %}
{% if settings.memo_title and settings.memo_msg %}
<div class="post-list-outline index-memo">
<h2 class="label">{{ settings.memo_title }}</h2>
<div>
{% autoescape off %}{{ settings.memo_msg }}{% endautoescape %}
</div>
</div>
{% endif %}
{% if announcements and request.user.is_authenticated %}
<div class="tleft">
<div class="post-list-outline">
@@ -46,17 +55,6 @@
</div>
</div>
</div>
</div>
{% endif %}
{% if WelcomeMSG and not request.user.is_authenticated %}
<div class="post-list-outline index-memo">
<h2 class="label">Welcome to {{ brand_name }}!</h2>
{% for WelcomeMSG in WelcomeMSG %}
<h2>{{ WelcomeMSG.Title }}</h2>
<p>{{ WelcomeMSG.message|linebreaksbr|urlize }}</p>
{% if WelcomeMSG.image %}<image src={{ WelcomeMSG.image.url }}></image>{% endif %}
{% endfor %}
</div>
{% endif %}
{% if request.user.c_tokens > 0 %}<a class="big-button" href={% url "main:community-create" %}><span class="symbol-label">Create a community</span></a>{% endif %}
@@ -97,6 +95,12 @@
{% community_page_element user_communities "Popular User-Created Communities" False "usr" %}
{% if user_communities %}<a href="{% url "main:community-viewall" "usr" %}" class="big-button">Show more</a>{% endif %}
{% community_page_element my_communities "My Communities" %}
{% if not feature and not game and not special and not user_communities and not my_communities %}
<div class="post-list-outline">
{% nocontent "There are no communities of any kind yet. You can either create one in the admin panel, or make a user-created community once you sign up." %}
</div>
{% endif %}
</div>
<div id="community-guide-footer">
<div id="guide-menu">
@@ -10,7 +10,7 @@
<li class="setting-community-name">
<p class="settings-label">Set name:</p>
<div class="center center-input">
<input type="text" name="community_name" maxlength="32" placeholder="New Name" value="{{ community.name }}">
<input type="text" name="community_name" maxlength="64" placeholder="New Name" value="{{ community.name }}">
</div>
</li>
<li class="setting-community-description">
@@ -32,7 +32,11 @@
<input accept="image/gif, image/png, image/webp, image/jpeg, image/jpg, image/svg+xml, image/bmp" type="file" style="display: none;" name="community_banner" onchange="loadFile(event)" id="upload-file">
</label>
</li>
<<<<<<< Updated upstream
{% endif %}
=======
{% endif %}
>>>>>>> Stashed changes
<li>
<p>&nbsp;</p>
<input type="checkbox" name="force_login" {% if community.require_auth %}checked{% endif %}>Require login:
@@ -1,6 +1,16 @@
{% extends "closedverse_main/layout.html" %}{% block main-body %}{% load closedverse_community %}
{% community_sidebar community request %}
<div class="main-column">
{% if user.is_warned %}
<div class="notice" style="background-color: #ffc783;border: 1px solid #ffb358;">
<p><b>WARNING</b>: You have been issued a warning by an administrator.
<div>
{% if user.get_warned_reason %}
<p>Reason: "{{ user.get_warned_reason }}"</p>
{% endif %}
</div>
</div>
{% endif %}
<div class="post-list-outline">
<h2 class="label">{{ community.name }}</h2>
{% if request.user.is_authenticated and community.post_perm %}
@@ -1,11 +1,11 @@
{% load closedverse_user %}{% if profile.can_block %}
{% load closedverse_user %}
<div class="dialog none" data-modal-types="post-block">
<div class="dialog-inner">
<div class="window">
<h1 class="window-title">{% if profile.is_blocked %}Unblock{% else %}Block{% endif %} {{ user.nickname }}</h1>
<div class="window-body">
{% user_sidebar_info user profile %}
<form method="post" data-action="{% url "main:user-addblock" user.username %}">
<form method="post" data-action="{% if profile.is_blocked %}{% url "main:user-rmblock" user.username %}{% else %}{% url "main:user-addblock" user.username %}{% endif %}">
<p class="window-body-content">Really {% if profile.is_blocked %}un{% endif %}block this user?{% if not profile.is_blocked %} You won't be able to see each other's posts or profile.{% endif %}</p>
<div class="form-buttons">
<input type="button" class="olv-modal-close-button gray-button" value="No">
@@ -16,4 +16,3 @@
</div>
</div>
</div>
{% endif %}
@@ -45,6 +45,6 @@
<div class="form-buttons">
<input type="submit" class="black-button reply-button disabled" value="Send" data-community-id="{{ post.community.unique_id }}" data-url-id="{{ post.id }}" data-post-content-type="text" data-post-with-screenshot="nodata" disabled="">
<input type="submit" class="black-button reply-button disabled" value="Send" data-url-id="{{ post.id }}" data-post-content-type="text" data-post-with-screenshot="nodata" disabled="">
</div>
</form>
@@ -1,5 +1,5 @@
{% if not post.is_rm %}
{% load closedverse_tags %}<div id="{{ post.unique_id }}" {% if post.spoils and not post.is_mine or not post.creator.is_active %}data-href-hidden{% else %}data-href{% endif %}="{% if post.is_reply %}{% url "main:comment-view" post.id %}{% else %}{% url "main:post-view" post.id %}{% endif %}" class="post post-subtype-default trigger{% if post.spoils and not post.is_mine or not post.creator.is_active or post.user_is_blocked %} hidden test-hidden{% endif %}{% if type == 2 %} post-list-outline{% endif %}" tabindex="0">
{% load closedverse_tags %}<div id="post-{{ post.id }}" {% if post.spoils and not post.is_mine or not post.creator.is_active %}data-href-hidden{% else %}data-href{% endif %}="{% if post.is_reply %}{% url "main:comment-view" post.id %}{% else %}{% url "main:post-view" post.id %}{% endif %}" class="post post-subtype-default trigger{% if post.spoils and not post.is_mine or not post.creator.is_active or post.user_is_blocked %} hidden test-hidden{% endif %}{% if type == 2 %} post-list-outline{% endif %}" tabindex="0">
{% if with_community_container %}
<p class="community-container">
{% if post.is_reply %}
@@ -81,7 +81,7 @@
View all comments ({{ post.number_comments }})
</div>
{% endif %}
<div id="{{ post.recent_comment.unique_id }}" tabindex="0" class="recent-reply trigger">
<div tabindex="0" class="recent-reply trigger">
{% user_icon_container post.recent_comment.creator post.recent_comment.feeling %}
<p class="user-name"><a href="{% url "main:user-view" post.recent_comment.creator.username %}">{{ post.recent_comment.creator.nickname }}</a></p>
<p class="timestamp-container">
@@ -1,6 +1,6 @@
{% load closedverse_tags %}<div id="empathy-content"{% if not yeahs %} class="none"{% endif %}>
{% if myself.is_authenticated %}<a href="{% url "main:user-view" myself.username %}" class="post-permalink-feeling-icon visitor {% user_class myself %}"{% if not has_yeah %} style="display: none;"{% endif %}><img src="{% avatar myself %}" class="user-icon"></a>{% endif %}
{% if myself.is_authenticated %}<a href="{% url "main:user-view" myself.username %}" {% if not has_yeah %} style="display: none;"{% endif %} class="post-permalink-feeling-icon visitor{% if myself.get_class.0 %} official"><img src="{% user_class myself %}" class="official-tag">{% else %}">{% endif %}<img src="{% avatar myself %}" class="user-icon"></a>{% endif %}
{% for yeah in yeahs %}{% if not myself.is_authenticated or not yeah.by == myself %}
<a href="{% url "main:user-view" yeah.by.username %}" class="post-permalink-feeling-icon {% user_class yeah.by %}"><img src="{% avatar yeah.by yeah.feeling %}" class="user-icon"></a>
<a href="{% url "main:user-view" yeah.by.username %}" class="post-permalink-feeling-icon{% if yeah.by.get_class.0 %} official"><img src="{% user_class yeah.by %}" class="official-tag">{% else %}">{% endif %}<img src="{% avatar yeah.by yeah.feeling %}" class="user-icon"></a>
{% endif %}{% endfor %}
</div>
@@ -1,4 +1,4 @@
{% load closedverse_tags %}{% load closedverse_user %}<div class="dialog none" data-modal-types="accept-friend-request" uuid="{{ fr.unique_id }}" data-screen-name="{{ fr.source.nickname }}" data-reject-action="{% url "main:user-fr-reject" fr.source.username %}" data-action="{% url "main:user-fr-accept" fr.source.username %}">
{% load closedverse_tags %}{% load closedverse_user %}<div class="dialog none" data-modal-types="accept-friend-request" data-screen-name="{{ fr.source.nickname }}" data-reject-action="{% url "main:user-fr-reject" fr.source.username %}" data-action="{% url "main:user-fr-accept" fr.source.username %}">
<div class="dialog-inner">
<div class="window">
<h1 class="window-title">Friend Request from {{ fr.source.nickname }} at {% time fr.created True %}</h1>
@@ -1,8 +1,8 @@
{% load markdown_deux_tags %}{% load closedverse_tags %} <div class="post scroll {% if message.mine %}my{% else %}other{% endif %}" id="{{ message.unique_id }}">
{% load markdown_deux_tags %}{% load closedverse_tags %} <div class="post scroll {% if message.mine %}my{% else %}other{% endif %}" id="message-{{ message.id }}">
{% user_icon_container message.creator message.feeling %}
<p class="timestamp-container">
<span class="timestamp">{% time message.created %}{% if message.read %} - Read{% endif %}</span>
<button type="button" class="symbol button edit-button rm-post-button" data-action="{% url "main:message-delete" message.unique_id %}"><span class="symbol-label">Delete</span></button>
<button type="button" class="symbol button edit-button rm-post-button" data-action="{% url "main:message-delete" message.id %}"><span class="symbol-label">Delete</span></button>
</p>
<div class="post-body">
{% if message.drawing %}
@@ -1,4 +1,4 @@
{% if not comment.is_rm %}{% load closedverse_tags %}<li id="{{ comment.unique_id }}" {% if comment.spoils and not comment.is_mine or not comment.creator.is_active %}data-href-hidden{% else %}data-href{% endif %}="{% url "main:comment-view" comment.id %}" class="post {% if comment.owner_post %}my{% else %}other{% endif %}{% if comment.spoils and not comment.is_mine or not comment.creator.is_active %} hidden{% endif %} trigger">
{% if not comment.is_rm %}{% load closedverse_tags %}<li id="comment-{{ comment.id }}" {% if comment.spoils and not comment.is_mine or not comment.creator.is_active %}data-href-hidden{% else %}data-href{% endif %}="{% url "main:comment-view" comment.id %}" class="post {% if comment.owner_post %}my{% else %}other{% endif %}{% if comment.spoils and not comment.is_mine or not comment.creator.is_active %} hidden{% endif %} trigger">
{% user_icon_container comment.creator comment.feeling %}
<div class="body">
<div class="header">
@@ -1,7 +1,6 @@
{% load closedverse_community %}
<form id="post-form" method="post" action="{% url "main:post-create" community.id %}" class="folded for-identified-user" data-post-subtype="default" name="test-post-default-form">
{% csrf_token %}
<input type="hidden" name="community" value="{{ community.unique_id }}">
{% if not user.limit_remaining is False %}
<div class="post-count-container">
<span>Remaining posts for today</span>
@@ -59,6 +58,6 @@
<div class="form-buttons">
<input type="submit" class="black-button post-button disabled" value="Send" data-community-id="{{ community.unique_id }}" data-post-content-type="text" data-post-with-screenshot="nodata" disabled="">
<input type="submit" class="black-button post-button disabled" value="Send" data-post-content-type="text" data-post-with-screenshot="nodata" disabled="">
</div>
</form>
@@ -1 +1 @@
<a href="{% url "main:user-view" user.username %}" class="icon-container {{ uclass }} {% if user.online_status == True %}online{% elif user.online_status == 2 %}afk{% elif user.online_status == False %}offline{% endif %}"><img src="{{ url }}" class="icon"></a>
<a href="{% url "main:user-view" user.username %}" class="icon-container {% if user.online_status == True %}online{% elif user.online_status == 2 %}afk{% elif user.online_status == False %}offline{% endif %}{% if uclass %} official"><img src="{{ uclass }}" class="official-tag">{% else %}">{% endif %}<img src="{{ url }}" class="icon"></a>
@@ -1,5 +1,5 @@
{% load closedverse_tags %}<div id="sidebar-profile-body"{% if profile.favorite %} class="with-profile-post-image"{% endif %}>
<div class="icon-container {% user_class user %} {% if user.online_status == True %}online{% elif user.online_status == 2 %}afk{% elif user.online_status == False %}offline{% endif %}">
<div class="icon-container {% if user.online_status == True %}online{% elif user.online_status == 2 %}afk{% elif user.online_status == False %}offline{% endif %}{% if user.get_class.0 %} official"><img src="{% user_class user %}" class="official-tag">{% else %}">{% endif %}
<a href="{% url "main:user-view" user.username %}">
<img src="{% avatar user %}" alt="{{ user.nickname }}" class="icon">
</a>
@@ -53,8 +53,11 @@
{% if not has_authority and request.user.can_manage %}
<button class="button" data-href="{% url "main:user-tools" user.username %}">User Settings</button>
{% endif %}
{% if not user.is_me and profile.can_block %}
<button type="button" class="button block-button">{% if profile.is_blocked %}Unblock{% else %}Block{% endif %}</button>
{% if not general and not user.is_me and profile.can_block %}
<div class="report-buttons-content">
<!-- for later use <button type="button" class="report-button report-user" data-track-label="user" data-track-action="openReportModal" data-track-category="reportViolator" data-modal-open="#report-violator-page">Report Violation</button> -->
<button type="button" class="report-button block-button">{% if profile.is_blocked %}Unblock{% else %}Block{% endif %}</button>
</div>
{% endif %}
</div>
@@ -175,7 +178,7 @@
{% endif %}
{% if profile.external %}
<div class="data-content">
<h4><span>Discord Tag</span></h4>
<h4><span>Discord</span></h4>
<div class="note">
<span>{{ profile.external }}</span>
</div>
@@ -3,8 +3,9 @@
<div class="main-column center">
<div class="post-list-outline login-page">
<form method="post">
<img src="{% static "img/menu-logo.svg" %}">
<img src="{{ brand_logo }}">
<p class="lh">{{ title }}</p>
{% if reset_supported %}
<p>If you've forgotten your password or need to reset it for some reason, you've come to the right place.<br>Yes, this works.</p>
<h3 class="label"><label>E-mail address: <input type="email" class="auth-input" name="email" placeholder="Email" required></label></h3>
{% csrf_token %}
@@ -14,6 +15,11 @@
<p>Having issues? Want to get back into your account? Try <a href="{% url "main:help-contact" %}">contacting us</a> if you need help with this.</p>
<p>Notice: Your user ID is used to log in, and is sometimes referred to as a username. It is below your nickname in most cases, please make sure you are using your user ID and your password.</p>
</div>
{% else %}
<p>Password resets are not enabled on this instance of {{ brand_name }}.
<p>To remedy this, tell the owner of the service to set up an SMTP server and specify it in their {{ brand_name }} configuration.</p>
<br>
{% endif %}
</form>
</div>
</div>
@@ -3,9 +3,9 @@
<div class="main-column center">
<div class="post-list-outline login-page">
<form method="post">
<img src="{% static "img/menu-logo.svg" %}">
<p class="lh">Reset password</p>
<p>Hello {{ user.username }}, it's time to reset your password.</p>
<img src="{{ brand_logo }}">
<p class="lh">{{ title }}</p>
<p>Welcome back, {{ user.username }}! It's time to reset your password.</p>
<h3 class="label"><label>New password: <input type="password" class="auth-input" name="password" placeholder="Password" required></label></h3>
<h3 class="label"><label>Confirm new password: <input type="password" class="auth-input" name="password_again" placeholder="Password again" required></label></h3>
{% csrf_token %}
@@ -13,7 +13,7 @@
<button type="submit" class="button">Reset</button>
</form>
<div class="ll">
<p>Once finished you can log into your account with your new password.</p>
<p>Having issues? Want to get back into your account? Try <a href="{% url "main:help-contact" %}">contacting us</a> if you need help with this.</p>
</div>
</div>
</div>
@@ -27,7 +27,7 @@
<div class="list news-list">
{% if friendrequests %}
{% for fr in friendrequests %}
<div class="news-list-content trigger" tabindex="0" id="{{ fr.unique_id }}" data-href="{% url "main:user-view" fr.source.username %}">
<div class="news-list-content trigger" tabindex="0" data-action="{% url "main:user-fr-accept" fr.source.username %}" data-href="{% url "main:user-view" fr.source.username %}">
{% user_icon_container fr.source %}
<div class="body">
<a href="{% url "main:user-view" fr.source.username %}" class="nick-name"{% if fr.source.color %}style=color:{{ fr.source.color }}{% endif %}>{{ fr.source.nickname }}</a><br><span class="timestamp"> {% time fr.created %}</span>
@@ -6,7 +6,7 @@
<h2 class="label">Frequently Asked Questions (FAQ)</h2>
<div id="guide" class="help-content">
<div class="faq">
<p>Hey there! If you have any questions about Cedar, this page aims to answer them.</p>
<p>Hey there! If you have any questions about this instance of {{ brand_name }}, this page aims to answer them.</p>
<h2>What is Cedar?</h2>
<p>Cedar is a social network that offers a safe and secure platform for users to connect and share. It is based on the Closedverse project and has some unique features compared to other sites, such as customizable communities and a drawing tool.</p>
<h3>The history of cedar</h3>
@@ -35,4 +35,4 @@
</div>
</div>
</div>
{% endblock %}--
{% endblock %}
@@ -3,7 +3,7 @@
<div class="main-column center">
<div class="post-list-outline login-page">
<form method="post">
<img src="{% static "img/menu-logo.png" %}">
<img src="{{ brand_logo }}">
<p class="lh">Reset password</p>
<p>Welcome back! It appears you've got the email, and now it's time to reset your password.</p>
<form method="post">
@@ -1,60 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Legal info</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap for this, why not? -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<center>
<h2>Closedverse - legal info</h2>
<h3>Copyright information</h3>
</center>
<pre style="white-space:pre-wrap;">
This project is not, in any way, associated with Nintendo Co, Ltd. or Hatena Co, Ltd.
Nintendo and Hatena have no involvement with this service, neither company maintains, endorses, sponsors or contributes to this. This is solely maintained, paid for, and created by Arian Kordi et al.
Please do not C&amp;D me, let me know beforehand and I will attempt to solve an issue if there is one.
If anything here infringes on your rights, please contact me:
<a href="mailto:[email protected]">[email protected]</a>
or
<a href="mailto:[email protected]">[email protected]</a>
The specified content that does not belong to Arian Kordi, the owner, is:
* The spinner "spinner-wandering-cubes" seen in Activity Feed loading, scrolling (Autopagerize), and admin management loading, which is owned and designed entirely by <em>Hammer & Chisel (Discord)</em>
* The majority of the JavaScript, CSS and HTML files and the style of <em>Miiverse</em> is owned entirely by <em>Hatena Co, Ltd.</em> and <em>Nintendo Co, Ltd.</em>
* The loading animation, originally taken from <em><a href="https://splatoon.nintendo.net/">SplatNet</a></em> and <em>Splatoon</em> by <em>Nintendo Co, Ltd.</em> and modified
I will take this project and <a href="https://github.com/ariankordi/closedverse">its GitHub repository</a> down under any valid request.
Thank you!
<em>Revision 4, updated October 21 2017</em></pre>
<center>
<h3>User content policy</h3>
</center>
<pre style="white-space:pre-wrap;">
User content is not owned by me or the site. Any users' content (posts, empathies or Yeah!s, follows, friend requests, friendships, private messages, etc..) <strong>is their sole responsibility.</strong>
I am not and do not want to be deemed responsible if any user transmits content that can spawn a legal problem.
I am only a host for the content and so is the image hosting provider(s) if applicable.
If you have a problem that requires attention by <strong>me</strong>, please contact me:
<a href="mailto:[email protected]">[email protected]</a>
or
<a href="mailto:[email protected]">[email protected]</a>
If you feel you have the need to contact law enforcement for any case, please do so. Don't contact me if you have a major legal problem. I will not forward anything to your police department because I don't have the time and I don't know where you live.
Every user must be 13 years of age or older in order to use the site. We do not follow (and personally heavily deplore) any child protection acts, such as COPPA. Any user under 12 years of age is not permitted to use this site.
Thank you!
<em>Revision 3, updated October 6 2017</em></pre>
<button type="button" class="btn btn-primary" onclick="window.history.back();">Go back</button>
{% extends "closedverse_main/layout.html" %}
{% block main-body %}{% load closedverse_user %}
{% user_sidebar request user user.profile 0 True %}
<div class="main-column" id="help">
<div class="post-list-outline">
<h2 class="label">Legal Information</h2>
<div class="help-content">
<h2>Is this actually legal?</h2>
<p>Probably not.</p>
<h2>I'm Nintendo and I want to fucking sue you.</h2>
<p>Please do not do that, I have a waifu and family to feed. <a href="{% url "main:help-contact" %}">Contact me instead.</a></p>
</div>
</body>
</html>
</div>
</div>
{% endblock %}
@@ -1,7 +1,7 @@
{% extends "closedverse_main/layout.html" %}
{% block main-body %}{% load closedverse_user %}
{% user_sidebar request user user.profile 0 True %}
<div id="help" class="main-column">
<div class="main-column" id="help">
<div class="post-list-outline">
<h2 class="label">Cedar Rules</h2>
<div class="help-content">
@@ -6,7 +6,6 @@
<h2 class="label">Server statistics</h2>
<div id="guide" class="help-content">
<div class="faq">
<p>These are the current stats of this Cedar instance:</p>
<ul>
<li>Communities: <strong>{{ communities }}</strong></li>
<li>Posts: <strong>{{ posts }}</strong></li>
@@ -104,12 +104,12 @@
<div id="wrapper"{% if not request.user.is_authenticated %} class="guest"{% endif %}>
<div id="sub-body">
<menu id="global-menu">
<li id="global-menu-logo"><h1><a href="/"><img src="{% static "img/menu-logo.svg" %}" alt="{{ brand_name }}"></a></h1></li>
{% if request.user.unique_id %}
<li id="global-menu-logo"><h1><a href="/"><img src="{{ brand_logo }}" alt="{{ brand_name }}"></a></h1></li>
{% if request.user.is_authenticated %}
{% invite_only request as inv %}
<li id="global-menu-list">
<ul>
<li id="global-menu-mymenu"><a href="{% url "main:user-view" request.user.username %}"><span class="icon-container {% user_class request.user %}"><img src="{% avatar request.user %}" alt="User Page"></span><span>User Page</span></a></li>
<li id="global-menu-mymenu"><a href="{% url "main:user-view" request.user.username %}"><span class="icon-container {% if request.user.get_class.0 %} official"><img src="{% user_class request.user %}" class="official-tag">{% else %}">{% endif %}<img src="{% avatar request.user %}" alt="User Page"></span><span>User Page</span></a></li>
<li id="global-menu-feed"><a href="{% url "main:activity" %}" class="symbol"><span>Activity Feed</span></a></li>
<li id="global-menu-community"><a href="/" class="symbol"><span>Communities</span></a></li>
<li id="global-menu-message"><a href="{% url "main:messages" %}" class="symbol"><span>Messages</span></a></li>
@@ -125,6 +125,7 @@
<li><a href="{% url "main:help-rules" %}" class="symbol my-menu-guide"><span>{{ brand_name }} Rules</span></a></li>
<li><a href="#" class="symbol my-menu-white-power"><span>Feedback/bug report</span></a></li>
<li><a href="{% url "main:server-stat" %}" class="symbol my-menu-openman"><span>Server Statistics</span></a></li>
<li><a href="{% url "main:block-list" %}" class="symbol my-menu-openman"><span>My block list</span></a></li>
<li>
<form action="{% url "main:logout" %}" method="post" id="my-menu-logout" class="symbol">
{% csrf_token %}
@@ -3,9 +3,9 @@
<div class="main-column center">
<div class="post-list-outline login-page">
<form method="post">
<img src="{% static "img/menu-logo.svg" %}">
<h1 class="lh">Sign In</h1>
<h2 class="lh">Please sign in to access {{ brand_name }}.</h2>
<img src="{{ brand_logo }}">
<p class="lh">Log In</p>
<p>Sign in to access this instance of {{ brand_name }}</p>
<div class="login-box">
<h3 class="label"><input type="text" class="auth-input" name="username" maxlength="32" placeholder="Username"></h3>
<h3 class="label"><input type="password" class="auth-input" name="password" maxlength="32" placeholder="Password"></h3>
@@ -15,18 +15,17 @@
<p class="red" style="margin-bottom:6px"></p>
<button type="submit" class="black-button">Sign In</button>
<div class="ll">
{% if allow_signups %}
<div class="ll">
<p>Can't remember your password? <a href="{% url "main:forgot-passwd" %}"> Reset it here!</a></a></p>
<p>If you don't have an account, you're in luck! <a href="{% url "main:signup" %}"> You can create an account there.</a></a></p>
</div>
{% endif %}
{% if not allow_signups %}
<div class="ll">
<p>If you don't have an account, <a href="{% url "main:signup" %}"><b>sign up</b> here.</a></p>
{% else %}
<p>Signing up is disabled for now, check back later.</p>
</div>
{% endif %}
{% if reset_supported %}
<p>If you forgot your password, <a href="{% url "main:forgot-passwd" %}"><b>reset</b> it here.</a></p>
{% endif %}
<br><p>If you need help with logging in, see the <a href="{% url "main:help-login" %}"><b>login help</b></a> page.</p>
</div>
</form>
</div>
</div>
@@ -3,61 +3,50 @@
<div class="main-column"><div class="post-list-outline">
<h2 class="label">Change settings for {{ user.username }}</h2>
<form class="setting-form" method="post" action={% url "main:user-tools-set" user.username %}>
<p>Yes, this form is now ugly, but it's way more powerful.</p>
<li class="setting">
{% user_sidebar_info user %}
<p class="settings-label">Set Username:</p>
<div class="center center-input">
<input type="text" name="username" maxlength="32" placeholder="New Username" value="{{ user.username }}">
</div>
<p class="note">Change the account username here.<br />If you need to change this, make sure the user is aware of the change, otherwise they won't be able to log in.</p>
</li>
</li>
<li class="setting-profile-comment">
<p class="settings-label">Profile comment:</p>
<textarea class="textarea" name="profile_comment" maxlength="2200" placeholder="Profile comment">{{ profile.comment }}</textarea>
<p class="note">In case you need to change something in this person's profile comment, you can do so here.</p>
</li>
<li class="setting">
<p class="settings-label">Set Nickname:</p>
<div class="center center-input">
<input type="text" name="nickname" maxlength="32" placeholder="New Username" value="{{ user.nickname }}">
</div>
<p class="note">Change the account nickname here</p>
</li>
<li class="setting">
<p class="settings-label">Specify warning or ban reason:</p>
<div class="center center-input">
<input type="text" name="warned_reason" maxlength="400" placeholder="Reason" value="{% if user.warned_reason %}{{ user.warned_reason }}{% endif %}">
</div>
<p class="note">If you are going to warn or disable someone, PLEASE SPECIFY WHY HERE!<br />Nothing feels worse than to get banned or warned without knowing why.</p>
<input type="checkbox" name="warned" {% if user.warned %}checked{% endif %}>Show warning
</li>
<li class="setting">
<p class="settings-label">Account restrictions:</p>
<input type="checkbox" name="active" {% if not user.active %}checked{% endif %}>Disable account:
<p class="note">Check this setting to disable the account and prevent new accounts from being made. This is basically the main way to ban people. Remember to specify a reason for doing this.</p>
{% for field in user_form %}
<li class='setting'>
{% if field.field.widget.input_type == 'checkbox' %}
<p>&nbsp;</p>
<input type="checkbox" name="cannot_edit" {% if profile.cannot_edit %}checked{% endif %}>Lock user settings:
<p class="note">If you need to lock someone's profile settings, you can do that here!</p>
<input type="number" name="post_limit" min="0" max="999" value="{{ profile.limit_post }}"> Post limit:
<p class="note">If you need to set a post limit for someone, you can do that here, Set this back to "0" to remove the restriction.</p>
<input type="checkbox" name="let_freedom" {% if not profile.let_freedom %}checked{% endif %}>Restrict image posting:
<p class="note">If you need to prevent someone from posting images and URLs, you can do that here. This will also prevent this user from making new accounts on the same IP address.</p>
<input type="checkbox" name="can_invite" {% if not user.can_invite %}checked{% endif %}>Restrict invite creation:
<p class="note">This site has an invitation function. If this invite function is active, users will need a code to sign up. Every user can make a code as long as they are allowed to do so. Check this box to prevent this user from making invites.</p>
{{ field }}{{ field.label_tag }}
{% elif field.field.widget.input_type == 'number' %}
<p class='settings-label'>{{ field.label_tag }}</p>
{{ field }}
{% else %}
<p class='settings-label'>{{ field.label_tag }}</p>
<div class="center-input">{{ field }}</div>
{% endif %}
<p class='note'>{{ field.help_text }}</p>
</li>
{% endfor %}
{% for field in profile_form %}
<li class='setting'>
{% if field.field.widget.input_type == 'checkbox' %}
<p>&nbsp;</p>
{{ field }}{{ field.label_tag }}
{% elif field.field.widget.input_type == 'number' %}
<p class='settings-label'>{{ field.label_tag }}</p>
{{ field }}
{% else %}
<p class='settings-label'>{{ field.label_tag }}</p>
<div class="center-input">{{ field }}</div>
{% endif %}
<p class='note'>{{ field.help_text }}</p>
</li>
{% endfor %}
</li>
<ul>
<li class="setting">
<p class="settings-label">Purge content:</p>
<input name="purge_posts" type="checkbox" />Purge posts:
<p class="note">Remove all posts from this user.</p>
<input name="purge_comments" type="checkbox" />Purge comments:
<p class="note">Remove all comments from this user.</p>
<p>&nbsp;</p>
<input name="restore_content" type="checkbox" />Restore comments and posts:
<p class="note">Restore purged comments and posts from this user.</p>
{% for field in purge_form %}
{{ field }}{{ field.label_tag }}
<p class='note'>{{ field.help_text }}</p>
{% endfor %}
</li>
</ul>
<li class="setting">
<div class="center center-input">
<p class="settings-label">Metadata:</p>
@@ -70,6 +59,7 @@
<a class='button' href="{% url "main:user-tools-meta" user.username %}">View private info</a>
{% endif %}
</div>
</li>
{% if accountmatch %}
<h3>Account(s) found with the same IP address.</h3>
<div class="user-data">
@@ -82,6 +72,7 @@
</table>
</div>
{% endif %}
{% if seen_by %}
<h3>Account viewed by:</h3>
<div class="user-data">
@@ -99,6 +90,7 @@
</table>
</div>
{% endif %}
{% if has_seen %}
<h3>This user has viewed:</h3>
<div class="user-data">
@@ -116,11 +108,11 @@
</table>
</div>
{% endif %}
</li>
{% csrf_token %}
<div class="form-buttons">
<input type="submit" class="black-button apply-button" value="Save">
<p class="note">More settings will be added soon!</p>
</div>
</form></div></div>
{% endblock %}
@@ -10,6 +10,7 @@
</h1>
</header>
{% if post.is_mine or post.can_rm %}
{% if user.is_active %}
<div class="edit-buttons-content">
<button type="button" class="symbol button edit-button rm-post-button" data-action="{% url "main:post-rm" post.id %}"><span class="symbol-label">Delete</span></button>
{% if post.is_mine and not post.has_edit %}
@@ -22,6 +23,7 @@
<button type="button" class="symbol button edit-button lock-comments-button" data-action="{% url "main:lock-the-comments" post.id %}"><span class="symbol-label">Lock comments</span></button>
{% endif %}
</div>
{% endif %}
{% endif %}
<div class="user-content">
@@ -70,7 +72,7 @@
{% endif %}
{% if post.poll %}
<div class="post-poll{% if post.poll.has_vote %} selected{% endif %}" data-action="{% url "main:poll-vote" post.poll.unique_id %}" data-action-unvote="{% url "main:poll-unvote" post.poll.unique_id %}">
<div class="post-poll{% if post.poll.has_vote %} selected{% endif %}" data-action="{% url "main:poll-vote" post.poll.id %}" data-action-unvote="{% url "main:poll-unvote" post.poll.id %}">
<a class="poll-votes">{{ post.poll.num_votes }} vote{% if not post.poll.num_votes == 1 %}s{% endif %}</a>
<div class="poll-options{% if post.screenshot %} with-background" style="background-image:url('{{ post.screenshot }}')"
<div class="poll-background" style="width:50%"></div>{% else %}">{% endif %}
@@ -76,11 +76,11 @@
<p class="note">If you want to advertise a URL of some sorts on your profile, this is where it goes.</p>
</li>
<li class="setting-website">
<p class="settings-label">Discord Tag</p>
<p class="settings-label">Discord Username</p>
<div class="center center-input">
<input type="text" name="external" maxlength="255" placeholder="Discord Tag" value="{{ profile.external }}">
</div>
<p class="note">Actually, you don't have to put a Discord Tag here, you can put anything here, such as your PlayStation Network account. Discord sure is popular though.</p>
<p class="note">Actually, you don't have to put a Discord username here, you can put anything here, such as your Threads username or X username. Discord sure is popular though.</p>
</li>
<li class="setting-website">
<p class="settings-label">What are you?</p>
@@ -3,7 +3,7 @@
<div class="main-column center">
<div class="post-list-outline login-page">
<form method="post" onload="">
<img src="{% static "img/menu-logo.svg" %}">
<img src="{{ brand_logo }}">
<p class="lh">Sign Up</p>
<p>Create a {{ brand_name }} account to make posts and comments to various communities, give Yeahs to other users' content, and interact with other members of the {{ brand_name }} community.</p><br>
<p>Please follow <a href="{% url "main:help-rules" %}">our rules</a>. If you don't, be careful with your behavior.<br><br>You <strong>must</strong> be {{ age }} years of age or older to join, no exceptions.<br>If you are suspected to be younger than {{ age }} years old, we will ban you until you're {{ age }}.</p>
@@ -5,7 +5,7 @@
<div class="main-column"><div class="post-list-outline">
<h2 class="label">Search Users</h2>
<form class="search user-search" action="{% url "main:user-search" %}">
<input type="text" name="query" value="{{ query }}" placeholder="SMF9, Robby, etc." minlength="1" maxlength="16">
<input type="text" name="query" value="{{ query }}" placeholder="Arian K, PF2M, etc." minlength="1" maxlength="16">
<input type="submit" value="q" title="Search">
</form>
{% if users %}
@@ -1,6 +1,6 @@
{% extends "closedverse_main/layout.html" %}
{% block main-body %}{% load closedverse_user %}
<div class="no-content"><div class="window-create-new-topic"><p>This user is blocked.</p>
{% if profile.can_block %}<div class="post-buttons-content"><button type="button" class="button block-button">Unblock</button></div>{% endif %}
<div class="post-buttons-content"><button type="button" class="button block-button">Unblock</button></div>
{% block_modal user profile %}
{% endblock %}
@@ -1 +0,0 @@
@@ -63,15 +63,19 @@ def empathy_txt(feeling=0, has=False):
1: 'Yeah!',
2: 'Yeah♥',
3: 'Yeah!?',
4: 'yeah...',
5: 'yeah...',
38: 'something something balls',
39: 'lol i lied',
69: 'Adam is gay.',
70: 'I am a faggot!',
71: 'Juice',
72: 'Commit Suicide',
73: 'Fresh!',
4: 'Yeah...',
5: 'Yeah...',
38: 'Nyeah~',
2012: 'olv.portal.miitoo.',
# 4: 'yeah...',
# 5: 'yeah...',
# 38: 'something something balls',
# 39: 'lol i lied',
# 69: 'Adam is gay.',
# 70: 'I am a faggot!',
# 71: 'Juice',
# 72: 'Commit Suicide',
# 73: 'Fresh!',
}.get(feeling, 'Yeah!')
# olv.portal.miitoo is going to be the only easter egg in this thing ever
@register.inclusion_tag('closedverse_main/elements/p_username.html')
+5 -10
View File
@@ -42,6 +42,8 @@ urlpatterns = [
url(r'users/'+ username +'/tools$', views.user_tools, name='user-tools'),
url(r'users/'+ username +'/tools/meta$', views.user_tools_meta, name='user-tools-meta'),
url(r'users/'+ username +'/block$', views.user_addblock, name='user-addblock'),
url(r'users/'+ username +'/block_rm$', views.user_rmblock, name='user-rmblock'),
url(r'my_blacklist$', views.user_blocklist, name='block-list'),
# Communities
url(r'communities.search$', views.community_search, name='community-search'),
url(r'communities/'+ community +'$', views.community_view, name='community-view'),
@@ -72,8 +74,8 @@ urlpatterns = [
url(r'comments/'+ comment +'/change$', views.comment_change, name='comment-change'),
url(r'comments/'+ comment +'/rm$', views.comment_rm, name='comment-rm'),
# Post-meta: polls
url(r'poll/(?P<poll>'+ uuidr +'+)/vote$', views.poll_vote, name='poll-vote'),
url(r'poll/(?P<poll>'+ uuidr +'+)/unvote$', views.poll_unvote, name='poll-unvote'),
url(r'poll/(?P<poll>[0-9]+)/vote$', views.poll_vote, name='poll-vote'),
url(r'poll/(?P<poll>[0-9]+)/unvote$', views.poll_unvote, name='poll-unvote'),
# Notifications
url(r'alive$', views.check_notifications, name='check-notifications'),
@@ -87,7 +89,7 @@ urlpatterns = [
url(r'pref$', views.prefs, name='prefs'),
url(r'settings/profile$', views.profile_settings, name='profile-settings'),
url(r'messages/?$', views.messages, name='messages'),
url(r'messages/(?P<message>'+ uuidr +'+)/rm$', views.message_rm, name='message-delete'),
url(r'messages/(?P<message>[0-9]+)/rm$', views.message_rm, name='message-delete'),
url(r'messages/'+ username +'$', views.messages_view, name='messages-view'),
url(r'messages/'+ username +'/read$', views.messages_read, name='messages-read'),
@@ -107,13 +109,6 @@ urlpatterns = [
url(r'help/login/?$', views.help_login, name='help-login'),
url(r'help/whatads/?$', views.whatads, name='what-ads'),
url(r'why/?$', views.help_why, name='help-why'),
# Util, right now we are away from the primary appo
url(r'origin$', views.origin_id, name='origin-id-get'),
# :^)
#url(r'openverse.png', views.openverse_logo, name='openverse-logo'),
]
# + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# serve static and media i think???? mighTTT???????
+130 -71
View File
@@ -2,12 +2,14 @@ from django.http import HttpResponse, HttpResponseNotFound, HttpResponseBadReque
from django.template import loader
from django.shortcuts import render, redirect, get_object_or_404
from django.http import Http404
from django.views.decorators.csrf import csrf_exempt
#from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth import login, logout
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods
from django.core.validators import EmailValidator
from django.core.exceptions import ValidationError
from django.contrib.auth.password_validation import validate_password
from django.contrib.auth import update_session_auth_hash
from django.db.models import Q, Count, Exists, OuterRef
from django.db.models.functions import Now
from .models import *
@@ -16,16 +18,12 @@ from closedverse import settings
import re
from django.urls import reverse
from random import getrandbits
from random import choice
from json import dumps, loads
import sys, traceback
import base64
import json
import traceback
import subprocess
from datetime import datetime, timedelta
from django.utils import timezone
import django.utils.dateformat
from binascii import hexlify
from os import urandom
from django.contrib.auth.hashers import identify_hasher
#from silk.profiling.profiler import silk_profile
@@ -67,8 +65,6 @@ def community_list(request):
ad = Ads.get_one()
else:
ad = "no ads"
WelcomeMSG = welcomemsg.objects.filter(show=True).order_by('-order', '-id')
# announcements within the past week-ish
announcements = Post.objects.filter(community__tags='announcements', created__gte=Now()-timedelta(days=5)).order_by('-created')[:6]
if request.user.is_authenticated:
@@ -79,7 +75,6 @@ def community_list(request):
'title': 'Communities',
'ad': ad,
'announcements': announcements,
'WelcomeMSG': WelcomeMSG,
'availableads': availableads,
'classes': classes,
'general': obj.filter(type=0).order_by('-created')[0:12],
@@ -97,7 +92,6 @@ def community_list(request):
'image': request.build_absolute_uri(settings.STATIC_URL + 'img/favicon.png'),
},
})
def community_all(request, category):
"""All communities, with pagination"""
try:
@@ -191,8 +185,9 @@ def community_favorites(request):
def login_page(request):
"""Login page! using our own user objects."""
# Redirect the user to / if they're logged in, forcing them to log out
location = '/'
if request.user.is_authenticated:
return redirect('/')
return redirect(location)
if request.method == 'POST':
# If we don't have all of the POST parameters we want..
if not (request.POST['username'] and request.POST['password']):
@@ -214,6 +209,17 @@ def login_page(request):
successful = False if user[1] is False or not user[0].is_active() else True
LoginAttempt.objects.create(user=user[0], success=successful, user_agent=request.META.get('HTTP_USER_AGENT'), addr=request.META.get('REMOTE_ADDR'))
if user[1] == False:
# check if a hasher could not be identified due to moving from passlib
try:
# will throw a ValueError if no hasher is found
identify_hasher(user[0].password)
except ValueError as e:
# error says "Unknown password hashing algorithm ''......", meaning that the password is not converted
if '\'\'' in str(e):
return HttpResponseBadRequest("The password is either encoded in an unsupported format, or the passwords haven't been updated yet. As part of a recent update, passwords need to be converted - sorry about that. If password resets work, you can use that to make your account usable immediately.")
else:
return HttpResponseBadRequest("The password is either encoded in an unsupported format, or the settings haven't been updated yet. Please add - or direct the server owner to add - hashers_passlib.bcrypt_sha256 to settings.PASSWORD_HASHERS, and then install django-hashers-passlib. I'm sorry for the inconvenience! If password resets work, you can use that immediately.")
else:
return HttpResponse("Invalid password.", status=401)
elif user[1] == 2:
return HttpResponse("This account's password needs to be reset. Contact an admin or reset by email.", status=400)
@@ -227,14 +233,17 @@ def login_page(request):
#if request.META['HTTP_REFERER'] and "login" not in request.META['HTTP_REFERER'] and request.META['HTTP_HOST'] in request.META['HTTP_REFERER']:
# location = request.META['HTTP_REFERER']
#else:
location = '/'
if request.GET.get('next'):
location = request.GET['next']
if request.headers.get('x-requested-with') == 'XMLHttpRequest':
# because if you respond to an ajax with a redirect, the response will just be the page, you can't get the redirect value from js
return HttpResponse(location)
return redirect(location)
else:
return render(request, 'closedverse_main/login_page.html', {
'title': 'Log in',
'allow_signups': settings.allow_signups,
'reset_supported': hasattr(settings, 'DEFAULT_FROM_EMAIL'),
#'classes': ['no-login-btn']
})
def signup_page(request):
@@ -311,8 +320,14 @@ def signup_page(request):
if not request.POST['password'] == request.POST['password_again']:
return HttpResponseBadRequest("Your passwords don't match.")
# do the length check
if len(request.POST['password']) < settings.minimum_password_length:
return HttpResponseBadRequest('The password must be at least ' + str(settings.minimum_password_length) + ' characters long.')
#if len(request.POST['password']) < settings.minimum_password_length:
# return HttpResponseBadRequest('The password must be at least ' + str(settings.minimum_password_length) + ' characters long.')
# use native django password validators, which can include length check
try:
# todo if you include the user object here it would help validate against some user attributes however this form is not the one that actually makes the account sooo not really doable unless a dummy user object is created for the sole purpose of this check which would be dumb
validate_password(request.POST['password'])
except ValidationError as error:
return HttpResponseBadRequest(error)
if not request.POST['nickname']:
return HttpResponseBadRequest("You need a nickname. What else are we gonna call you????? Ghosty?")
if request.POST['nickname'] and len(request.POST['nickname']) > 32:
@@ -363,7 +378,9 @@ def signup_page(request):
LoginAttempt.objects.create(user=make, success=True, user_agent=request.META.get('HTTP_USER_AGENT'), addr=request.META.get('REMOTE_ADDR'))
login(request, make)
request.session['passwd'] = make.password
return HttpResponse("/")
if request.headers.get('x-requested-with') == 'XMLHttpRequest':
return HttpResponse('/')
return redirect('/')
else:
if not settings.RECAPTCHA_PUBLIC_KEY:
settings.RECAPTCHA_PUBLIC_KEY = None
@@ -383,11 +400,19 @@ def forgot_passwd(request):
try:
user = User.objects.get(email=request.POST['email'])
except (User.DoesNotExist, ValueError):
<<<<<<< Updated upstream
return HttpResponseNotFound("There isn't a user with that email address.")
try:
user.password_reset_email(request)
except:
return HttpResponseBadRequest("There was an error submitting that.")
=======
return HttpResponseNotFound("The email address could not be found.")
try:
user.password_reset_email(request)
except Exception as error:
return HttpResponseBadRequest("There was an error submitting that, sorry! Here's why: " + str(error))
>>>>>>> Stashed changes
return HttpResponse("Success! Check your emails, it should have been sent from \"{0}\".".format(settings.DEFAULT_FROM_EMAIL))
if request.GET.get('token'):
user = User.get_from_passwd(request.GET['token'])
@@ -396,6 +421,10 @@ def forgot_passwd(request):
if request.method == 'POST':
if not request.POST['password'] == request.POST['password_again']:
return HttpResponseBadRequest("Your passwords don't match.")
try:
validate_password(new, user=user)
except ValidationError as error:
return HttpResponseBadRequest(error)
user.set_password(request.POST['password'])
user.save()
return HttpResponse("Success! Now you can log in with your new password!")
@@ -406,12 +435,17 @@ def forgot_passwd(request):
})
return render(request, 'closedverse_main/forgot_page.html', {
'title': 'Reset password',
'reset_supported': hasattr(settings, 'DEFAULT_FROM_EMAIL'),
#'classes': ['no-login-btn'],
})
def logout_page(request):
"""Password email page / post endpoint."""
if not request.user.is_active():
if not request.user.is_authenticated or not request.user.is_active():
if not request.user.is_authenticated:
logout(request)
r = HttpResponseForbidden("You are not logged in, so how can you possibly log out? You will be redirected to Wario Land 4 momentarily.", content_type='text/plain')
else:
r = HttpResponseForbidden("You can't log out while you're inactive. According to me and God, you'll just have to sit here and suffer for now. Go contemplate your actions. You will be redirected to Wario Land 4 momentarily.", content_type='text/plain')
r['Refresh'] = '7; url=https://gba.js.org/player#warioland4'
return r
@@ -524,7 +558,7 @@ def user_view(request, username):
user.avatar = request.POST.get('mh')
#profile.origin_id = getmii[2]
profile.origin_id = request.POST['origin_id']
profile.origin_info = dumps([request.POST.get('mh'), 'if you see this then something is wrong', request.POST['origin_id']])
profile.origin_info = json.dumps([request.POST.get('mh'), 'if you see this then something is wrong', request.POST['origin_id']])
# set the username color
if request.POST.get('color'):
try:
@@ -1031,6 +1065,7 @@ def community_tools_set(request, community):
can_edit = the_community.can_edit_community(request)
if not can_edit:
return HttpResponseForbidden()
<<<<<<< Updated upstream
if len(request.POST.get('community_name')) == 0 or len(request.POST.get('community_name')) >= 100:
return json_response('Your community name is either too short or too long.')
if len(request.POST.get('community_description')) >= 1024:
@@ -1087,6 +1122,24 @@ def community_tools_set(request, community):
'''
the_community.save()
#AuditLog.objects.create(type=2, user=user, by=request.user, reasoning=request.POST)
=======
form = CommunitySettingForm(request.POST, request.FILES, request , instance=the_community)
if not form.is_valid():
return json_response(form.errors.as_text())
community = form.save(commit=False)
community.name = form.cleaned_data.get('community_name')
community.description = form.cleaned_data.get('community_description')
community.platform = form.cleaned_data.get('community_platform')
community.require_auth = True if form.cleaned_data.get('force_login') else False
if form.cleaned_data.get('community_icon'):
upload = util.image_upload(form.cleaned_data.get('community_icon'), True, icon=True)
community.ico = upload
if form.cleaned_data.get('community_banner'):
upload = util.image_upload(form.cleaned_data.get('community_banner'), True, banner=True)
community.banner = upload
community.save()
AuditLog.objects.create(type=4, community=community, user=community.creator, by=request.user)
>>>>>>> Stashed changes
return HttpResponse()
else:
raise Http404()
@@ -1099,8 +1152,6 @@ def community_create(request):
raise Http404()
return render(request, 'closedverse_main/community_create.html', {
'title': 'Create a community',
'max_icon_size': settings.max_icon_size,
'max_banner_size': settings.max_banner_size,
'tokens': request.user.c_tokens,
})
def community_create_action(request):
@@ -1126,11 +1177,8 @@ def post_create(request, community):
if request.method == 'POST':
# Wake
request.user.wake(request.META['REMOTE_ADDR'])
# Required
if not (request.POST.get('community')):
return HttpResponseBadRequest()
try:
community = Community.objects.get(id=community, unique_id=request.POST['community'])
community = Community.objects.get(id=community)
except (Community.DoesNotExist, ValueError):
return HttpResponseNotFound()
# Method of Community
@@ -1352,13 +1400,13 @@ def comment_delete_yeah(request, comment):
@require_http_methods(['POST'])
@login_required
def poll_vote(request, poll):
the_poll = get_object_or_404(Poll, unique_id=poll)
the_poll = get_object_or_404(Poll, id=poll)
the_poll.vote(request.user, request.POST.get('a'))
return HttpResponse()
@require_http_methods(['POST'])
@login_required
def poll_unvote(request, poll):
the_poll = get_object_or_404(Poll, unique_id=poll)
the_poll = get_object_or_404(Poll, id=poll)
the_poll.unvote(request.user)
return HttpResponse()
@@ -1433,6 +1481,18 @@ def user_addblock(request, username):
user = get_object_or_404(User, username=username)
user.make_block(request.user)
return HttpResponse()
@require_http_methods(['POST'])
@login_required
def user_rmblock(request, username):
user = get_object_or_404(User, username=username)
user.remove_block(request.user)
return HttpResponse()
@login_required
def user_blocklist(request):
blocks = UserBlock.objects.filter(source=request.user).order_by('-created')[:50]
return render(request, 'closedverse_main/block-list.html', {
'blocks': blocks,
})
# Notifications work differently since the Openverse rebranding. (that we changed back)
# They used to respond with a JSON for values for unread notifications and messages.
@@ -1656,7 +1716,10 @@ def messages_read(request, username):
@require_http_methods(['POST'])
@login_required
def message_rm(request, message):
message = get_object_or_404(Message, unique_id=message)
message = get_object_or_404(Message, id=message)
# check that if you aren't the conversation source or target (so if you aren't inside the conversation)
if message.conversation.source != request.user and message.conversation.target != request.user:
raise Http404()
message.rm(request)
return HttpResponse()
@@ -1683,12 +1746,15 @@ def user_tools(request, username):
if not request.user.is_authenticated:
raise Http404()
if not request.user.can_manage():
raise Http404()
return HttpResponseForbidden()
user = get_object_or_404(User, username__iexact=username)
profile = user.profile()
# check if the requesting user is allowed to change someone
if user.has_authority(request.user):
raise Http404()
return HttpResponseForbidden()
user_form = UserForm(instance=user)
profile_form = ProfileForm(instance=profile)
purge_form = PurgeForm()
seen_by = MetaViews.objects.filter(target_user=user).distinct().order_by('-id')[:10]
has_seen = MetaViews.objects.filter(from_user=user).distinct().order_by('-id')[:10]
@@ -1699,6 +1765,9 @@ def user_tools(request, username):
return render(request, 'closedverse_main/man/usertools.html', {
'title': 'Admin tools',
'user': user,
'user_form': user_form,
'purge_form': purge_form,
'profile_form': profile_form,
'seen_by': seen_by,
'has_seen': has_seen,
'profile': profile,
@@ -1710,16 +1779,16 @@ def user_tools_meta(request, username):
if not request.user.is_authenticated:
raise Http404()
if not request.user.can_manage():
raise Http404()
return HttpResponseForbidden()
if request.user.level < settings.min_lvl_metadata_perms:
raise Http404()
return HttpResponseForbidden()
user = get_object_or_404(User, username__iexact=username)
profile = user.profile()
if user.protect_data:
return json_response('This user\'s data has been locked.')
return HttpResponseForbidden()
# check if the requesting user is allowed to view someone
if user.has_authority(request.user):
raise Http404()
return HttpResponseForbidden()
# get the last time the page was opened
last_opened = MetaViews.objects.filter(target_user=user, from_user=request.user).order_by('-created').first()
@@ -1756,43 +1825,25 @@ def user_tools_meta(request, username):
def user_tools_set(request, username):
if request.method == 'POST':
user = get_object_or_404(User, username__iexact=username)
profile = user.profile()
if not request.user.is_authenticated:
raise Http404()
if not request.user.can_manage():
raise Http404()
return HttpResponseForbidden()
# obtain instance of user and profile
user = get_object_or_404(User, username__iexact=username)
profile = user.profile()
if user.has_authority(request.user):
raise Http404()
if request.POST.get('username') == "" or None:
return json_response('Username Invalid')
if not re.compile(r'^[A-Za-z0-9-._]{1,32}$').match(request.POST['username']) or not re.compile(r'[A-Za-z0-9]').match(request.POST['username']):
return json_response("The username either contains invalid characters or is too long (only letters + numbers, dashes, dots and underscores are allowed")
if User.objects.filter(username=request.POST['username']).exists() and not request.POST['username'] == user.username:
return json_response("Username is taken, please pick a new name.")
if request.POST.get('nickname') == "" or None:
return json_response('Nickname Invalid')
if request.POST.get('post_limit') == "" or None:
return json_response('Post limit Invalid')
postlimitint = int(request.POST.get('post_limit'))
if postlimitint <= -1 or postlimitint >= 999:
return json_response('Post limit Invalid')
return HttpResponseForbidden()
user.warned_reason = (request.POST.get('warned_reason') or None)
user.username = request.POST.get('username')
profile.comment = request.POST.get('profile_comment')
user.nickname = request.POST.get('nickname')
profile.limit_post = int(request.POST.get('post_limit'))
user.active = True if request.POST.get('active') is None else False
user.warned = False if request.POST.get('warned') is None else True
profile.let_freedom = True if request.POST.get('let_freedom') is None else False
profile.cannot_edit = False if request.POST.get('cannot_edit') is None else True
user.can_invite = True if request.POST.get('can_invite') is None else False
purge_posts = False if request.POST.get('purge_posts') is None else True
purge_comments = False if request.POST.get('purge_comments') is None else True
restore_content = False if request.POST.get('restore_content') is None else True
user_form = UserForm(request.POST, instance=user)
profile_form = ProfileForm(request.POST, instance=profile)
purge_form = PurgeForm(request.POST)
if purge_form.is_valid():
purge_posts = purge_form.cleaned_data["purge_posts"]
purge_comments = purge_form.cleaned_data["purge_comments"]
restore_content = purge_form.cleaned_data["restore_all"]
# Probably (still) a better way to do this, but it's here for now.
if restore_content == True:
if purge_comments or purge_posts:
return json_response('You cannot purge and restore at the same time.')
@@ -1804,10 +1855,13 @@ def user_tools_set(request, username):
if purge_comments == True:
Comment.real.filter(creator=user).update(is_rm=True, status=5)
profile.save()
user.save()
AuditLog.objects.create(type=2, user=user, by=request.user, reasoning=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
AuditLog.objects.create(type=2, user=user, by=request.user)
return HttpResponse()
else:
return json_response('Error.' + user_form.errors.as_text() + profile_form.errors.as_text())
else:
raise Http404()
@@ -1897,7 +1951,7 @@ def my_data(request):
log_attempt = LoginAttempt.objects.filter(user=user).order_by('-id')[:10]
history = ProfileHistory.objects.filter(user=user).order_by('-id')[:10]
creation_date = user.created.date()
datenow = date.today()
datenow = timezone.now().date()
age = datenow - creation_date
return render(request, 'closedverse_main/help/my-data.html', {
'user': user,
@@ -1943,11 +1997,16 @@ def change_password_set(request):
if not user.check_password(old):
return json_response('The old password specified does not match the user\'s password. Enter the password you use as of right now.')
# do the length check
if len(new) < settings.minimum_password_length:
return json_response('The new password must be at least ' + str(settings.minimum_password_length) + ' characters long.')
#if len(new) < settings.minimum_password_length:
# return json_response('The new password must be at least ' + str(settings.minimum_password_length) + ' characters long.')
try:
validate_password(new, user=user)
except ValidationError as error:
return json_response(error)
# do the thing
user.set_password(new)
user.save()
update_session_auth_hash(request, user)
return json_response("Success! Now you can log in with your new password!")
else:
raise Http404
+11 -12
View File
@@ -1,22 +1,21 @@
#!/usr/bin/env python
#!/usr/bin/env python3
"""Django's command-line utility for administrative tasks."""
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "closedverse.settings")
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'closedverse.settings')
try:
from django.core.management import execute_from_command_line
except ImportError:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django
except ImportError:
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
)
raise
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
+2 -6
View File
@@ -230,7 +230,7 @@ form.search input[type="submit"] {
display: block;
border-right: 1px solid var(--theme-dark, #202030);
}
#global-menu li#global-menu-mymenu .icon-container img {
#global-menu li#global-menu-mymenu .icon-container img:not(.official-tag) {
border: 1px solid #000;
width: 36px;
height: 36px;
@@ -414,10 +414,6 @@ form.search {
background: #fff;
border: 2px solid #000;
}
.Announcement-content {
background: var(--theme-dark, #202030);
border: #000 solid 1px;
}
.sidebar-setting a {
color: #ccc;
border-top: 1px solid #000;
@@ -445,7 +441,7 @@ form.search {
.digest .post .icon-container {
border: 1px solid rgb(0, 0, 0);
}
#empathy-content .post-permalink-feeling-icon img {
#empathy-content .post-permalink-feeling-icon .user-icon {
border: 1px solid #000;
background: transparent;
}
+41 -17
View File
@@ -623,8 +623,8 @@ body {
width: 38px;
height: 38px;
}
#global-menu li#global-menu-mymenu .icon-container img {
border: 1px solid #dddddd;
#global-menu li#global-menu-mymenu .icon-container img:not(.official-tag) {
border: 1px solid #ddd;
width: 36px;
height: 36px;
-webkit-border-radius: 5px;
@@ -943,7 +943,7 @@ h2.reply-label {
border-left: none;
}
.community-switcher .community-switcher-tab.selected {
background: -webkit-gradient(linear, left top, left bottom, from(var(--theme, #257811)), to(var(--theme-slightly-dark, #1e610e)));
background: -webkit-gradient(linear, left top, left bottom, from(var(--theme, #257811)), to(var(--theme, #1e610e)));
background: -webkit-linear-gradient(top,#257811 #1e610e);
background: -moz-linear-gradient(top,#257811 #1e610e);
background: -ms-linear-gradient(top,#257811 #1e610e);
@@ -1194,7 +1194,7 @@ h2.label-topic .with-filter-right {
color: #FFF;
background: url("img/color-button-bg.gif") repeat-x 0 bottom var(--theme, #2e81e5);
background-color: #81e52e;
background: -webkit-gradient(linear, left top, left bottom, from(var(--theme, #257811)), to(var(--theme-slightly-dark, #1e610e)));
background: -webkit-gradient(linear, left top, left bottom, from(var(--theme, #257811)), to(var(--theme, #1e610e)));
background: -webkit-linear-gradient(top, #257811 #1e610e);
background: -moz-linear-gradient(top, #257811 #1e610e);
background: -ms-linear-gradient(top, #257811 #1e610e);
@@ -1272,10 +1272,19 @@ span.owner-label {
-o-border-radius: 5px;
border-radius: 5px;
}
.official-tag {
position: absolute;
display: block;
margin-top: -4px;
margin-left: -4px;
top: 0;
width: 22px;
height: 22px;
}
.icon-container.official {
position: relative;
}
.icon-container.official:after {
/*.icon-container.official:after {
position: absolute;
display: block;
margin-top: -4px;
@@ -1316,7 +1325,7 @@ span.owner-label {
.icon-container.verifiedd:after {
content: url("img/verified.png");
}
*/
.multi-timeline-post-list .post .icon-container.offline:before,
.multi-timeline-post-list .post .icon-container.online:before,
.multi-timeline-post-list .post .icon-container.afk:before {
@@ -1375,7 +1384,7 @@ span.owner-label {
width: 9px;
height: 9px;
}*/
/*
.post-permalink-feeling-icon.administrator {
position: relative;
}
@@ -1486,7 +1495,7 @@ span.owner-label {
left: 0;
width: 22px;
height: 22px;
}
}*/
.button {
-webkit-appearance: none;
-moz-appearance: none;
@@ -2982,8 +2991,10 @@ body.masked {
padding: 30px 25px 40px;
}
.dialog .dialog-inner {
/*
-webkit-backdrop-filter: blur(5px);
backdrop-filter: blur(5px);
*/
display: table-cell;
vertical-align: middle;
*display: inline;
@@ -6156,7 +6167,10 @@ h2.label-topic_post .label-topic_post-msgid {
height: 48px;
margin: 2px;
}
#empathy-content .post-permalink-feeling-icon img {
#empathy-content .post-permalink-feeling-icon .official-tag {
top: 8px;
}
#empathy-content .post-permalink-feeling-icon .user-icon {
width: 46px;
height: 46px;
border: 1px solid #222;
@@ -6697,7 +6711,7 @@ h2.label-topic_post .label-topic_post-msgid {
}
.index-memo h2:not(.label) {
margin-bottom: 5px;
margin-top: 14px;
margin-top: 10px;
}
#help .help-content .num1 h2 {
margin-top: 0;
@@ -7157,6 +7171,9 @@ h2.label-topic_post .label-topic_post-msgid {
box-shadow: none;
background-color: #f4f4f4;
}
#global-menu .official-tag {
top: 0px;
}
#global-menu li#global-menu-feed a,
#global-menu li#global-menu-community a {
padding-left: 0;
@@ -7580,7 +7597,7 @@ margin: 10px 0px 15px !important;
.simple-wrapper.simple-wrapper-content #main-body {
border: none;
}
#empathy-content .icon-container.donator:after,
/*#empathy-content .icon-container.donator:after,
#reply-content .icon-container.donator:after,
.news-list .icon-container.donator:after {
content: url(img/donator.png);
@@ -7643,6 +7660,7 @@ margin: 10px 0px 15px !important;
width: 17px;
height: 17px;
}
*/
.button {
font-size: 14px;
width: 85%;
@@ -8430,7 +8448,10 @@ margin: 10px 0px 15px !important;
height: 38px;
margin: 2px 1.5px 1px 1.5px;
}
#empathy-content .post-permalink-feeling-icon img {
#empathy-content .post-permalink-feeling-icon .official-tag {
top: 8px;
}
#empathy-content .post-permalink-feeling-icon .user-icon {
width: 36px;
height: 36px;
}
@@ -8530,7 +8551,7 @@ margin: 10px 0px 15px !important;
box-sizing: border-box;
}
#global-menu #global-menu-logo {
padding: 8px 0;
padding: 16px 0;
}
#global-menu #global-menu-logo img {
height: auto;
@@ -8846,9 +8867,10 @@ margin: 10px 0px 15px !important;
}
.login-page {
text-align: center;
padding: 10px;
}
.login-page > form > img {
margin-top: 30px;
margin-top: 20px;
margin-bottom: 10px;
max-width: 95%;
}
@@ -8858,7 +8880,7 @@ font-size: 20px;
}
.login-page .ll {
margin-top: 20px;
margin-bottom: 20px;
margin-bottom: 10px;
}
.login-page a:hover {
text-decoration: underline;
@@ -8869,14 +8891,16 @@ display: block;
width: 50%;
}
.index-memo {
margin-top: 10px;
text-align: center;
}
.index-memo > div {
padding: 10px;
}
.index-memo p {
width:90%;
display:inline-block;
}
#empathy-content .post-permalink-feeling-icon img {
#empathy-content .post-permalink-feeling-icon .user-icon {
border: 1px solid #dddddd;
}
+20 -3
View File
@@ -508,7 +508,7 @@ var Olv = Olv || {};
case 500:
errmsg = "An error has been encountered in the server.\n";
if(a.getResponseHeader('Content-Type').indexOf('html') < 0) {
window.tmpUnescapedHtmlForError = errmsg + "<br>Error information is available; please send this to an administrator:<code>" + b.SimpleDialog.htmlLineBreak(a.responseText) + "</pre>\n";
window.tmpUnescapedHtmlForError = errmsg + "<br>Error information is available; please send this to a developer:<code>" + b.SimpleDialog.htmlLineBreak(a.responseText) + "</pre>\n";
/*if(innerWidth <= 480) {
errmsg += a.responseText.substr(0, 400);
} else {
@@ -2595,7 +2595,8 @@ var Olv = Olv || {};
b.Closed.changesel("news");
$('.received-request-button').on('click', function(a) {
a.preventDefault()
fr = new b.ModalWindow($('div[data-modal-types=accept-friend-request][uuid='+ $(this).parent().parent().attr('id') +']'));fr.open();
window.ass = a
fr = new b.ModalWindow($('div[data-modal-types=accept-friend-request][data-action="'+ $(this).parent().parent().data('action') +'"]'));fr.open();
})
$('div[data-modal-types=accept-friend-request] .ok-button.post-button').on('click', function(a){
a.preventDefault();
@@ -3339,6 +3340,22 @@ mode_post = 0;
});
})
}),
b.router.connect("^/my_blacklist$", function() {
$('.received-request-button').on('click', function(a) {
a.preventDefault()
window.fr = new b.ModalWindow($('div#' + a.originalEvent.target.getAttribute('dataaa')));
window.fr.open();
});
$('div[data-modal-types=post-unblock] input.post-button').on('click', function(g){
g.preventDefault();
b.Form.toggleDisabled($(this), true);
b.Form.post(g.target.form.dataset.action).done(function() {
window.fr.close();
b.Form.toggleDisabled($(this), false);
b.Net.reload();
});
});
}),
b.router.connect("^/users/[^\/]+/(tools)$", function(c, d, e) {
function f(c) {
var d = a(this)
@@ -3495,7 +3512,7 @@ mode_post = 0;
$('.color-thing2').spectrum();
b.Net.reload();
var updateAvatar = function() {
a('#global-menu-mymenu .icon-container img').attr('src', a('#sidebar-profile-body .icon').attr('src'));
a('#global-menu-mymenu .icon-container .user-icon').attr('src', a('#sidebar-profile-body .icon').attr('src'));
var them = a('[name=theme]').val();
if(them === 'None') {
toDefault();
Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB