mirror of
https://github.com/Mistake35/Cedar-Django.git
synced 2026-07-17 16:11:14 +10:00
CVS merge
Yet even more code merged.
This commit is contained in:
+19
-4
@@ -171,11 +171,26 @@ nnid_forbiddens = BASE_DIR + '/forbidden.json'
|
||||
|
||||
# Client key to use for iphub.email, because we're using that
|
||||
# None for no IP checking (recommended since this is so slow)
|
||||
iphub_key = ""
|
||||
IPHUB_KEY = ""
|
||||
|
||||
# If IP can be checked, then use this to disallow any proxies
|
||||
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 = {
|
||||
r'^login/$',
|
||||
r'^signup/$',
|
||||
r'^logout/$',
|
||||
r'^reset/$',
|
||||
r'^help/rules$',
|
||||
r'^help/contact$',
|
||||
r'^help/login$',
|
||||
}
|
||||
|
||||
# MD
|
||||
MARKDOWN_DEUX_STYLES = {
|
||||
"default": {
|
||||
@@ -190,17 +205,17 @@ MARKDOWN_DEUX_STYLES = {
|
||||
allow_signups = True
|
||||
|
||||
# Whatever the reason may be, you have the option to make your clone invite only.
|
||||
invite_only = True
|
||||
invite_only = False
|
||||
|
||||
# Minimum level required to view IP addresses and user agents. (default: 10)
|
||||
# Mods under this level will still be able to manage users, however will not be able to view any sensitive data.
|
||||
min_lvl_metadata_perms = 100
|
||||
|
||||
# if someone's level is equal or above this, they can edit most community on your clone.
|
||||
level_needed_to_man_communities = 10
|
||||
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 = 10
|
||||
level_needed_to_man_users = 5
|
||||
|
||||
# file size limits in megabytes! only applies when using the community tools.
|
||||
max_icon_size = .5
|
||||
|
||||
@@ -59,7 +59,7 @@ class UserAdmin(admin.ModelAdmin):
|
||||
#form = UserForm
|
||||
class ProfileAdmin(admin.ModelAdmin):
|
||||
search_fields = ('id', 'unique_id', 'origin_id', )
|
||||
raw_id_fields = ('user', 'favorite', 'adopted', )
|
||||
raw_id_fields = ('user', 'favorite', )
|
||||
list_display = ('id', 'user', 'comment', 'let_freedom', )
|
||||
|
||||
class ComplaintAdmin(admin.ModelAdmin):
|
||||
|
||||
+102
-100
@@ -1,8 +1,7 @@
|
||||
from __future__ import unicode_literals
|
||||
from colorfield.fields import ColorField
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import BaseUserManager
|
||||
from django.db.models import Q, QuerySet, Max, F, Count, Case, When, Exists, OuterRef
|
||||
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
|
||||
@@ -51,7 +50,6 @@ class UserManager(BaseUserManager):
|
||||
user_agent = user_agent,
|
||||
email = email,
|
||||
)
|
||||
spamuser = True
|
||||
profile = Profile.objects.model()
|
||||
if nn:
|
||||
user.avatar = nn[0]
|
||||
@@ -64,10 +62,6 @@ class UserManager(BaseUserManager):
|
||||
user.has_mh = False
|
||||
user.set_password(password)
|
||||
user.save(using=self._db)
|
||||
if spamuser:
|
||||
profile.let_freedom = True
|
||||
else:
|
||||
profile.let_freedom = True
|
||||
profile.user = user
|
||||
profile.save()
|
||||
return user
|
||||
@@ -77,6 +71,7 @@ class UserManager(BaseUserManager):
|
||||
)
|
||||
user.set_password(password)
|
||||
user.staff = True
|
||||
user.level = 99 # added because some admin funcs are missing otherwise
|
||||
user.save()
|
||||
profile = Profile.objects.model()
|
||||
profile.user = user
|
||||
@@ -216,7 +211,7 @@ class User(models.Model):
|
||||
return None
|
||||
return infodecode[0]
|
||||
def has_plain_avatar(self):
|
||||
if not self.has_mh and 'http' in self.avatar and not 'gravatar.com' in self.avatar:
|
||||
if not self.has_mh and '/' in self.avatar and not 'gravatar.com' in self.avatar:
|
||||
return True
|
||||
def has_avatar(self):
|
||||
if not self.avatar or len(self.avatar) == 1:
|
||||
@@ -291,9 +286,9 @@ class User(models.Model):
|
||||
# Okay so this returns True if the user's online, 2 if they're AFK, False if they're offline and None if they hide it
|
||||
if self.hide_online:
|
||||
return None
|
||||
if (timezone.now() - timedelta(seconds=50)) > self.last_login:
|
||||
if (timezone.now() - timedelta(seconds=80)) > self.last_login:
|
||||
return False
|
||||
elif (timezone.now() - timedelta(seconds=48)) > self.last_login:
|
||||
elif (timezone.now() - timedelta(seconds=50)) > self.last_login: #
|
||||
return 2
|
||||
else:
|
||||
return True
|
||||
@@ -329,12 +324,13 @@ class User(models.Model):
|
||||
def num_friends(self):
|
||||
return self.friend_source.filter().count() + self.friend_target.filter().count()
|
||||
def can_follow(self, user):
|
||||
#if UserBlock.find_block(self, user):
|
||||
# return False
|
||||
if UserBlock.find_block(self, user):
|
||||
return False
|
||||
return True
|
||||
def can_view(self, user):
|
||||
#if UserBlock.find_block(self, user, full=True):
|
||||
# return False
|
||||
block = UserBlock.find_block(self, user)
|
||||
if block and block.target == user:
|
||||
return False
|
||||
return True
|
||||
def is_following(self, me):
|
||||
if not me.is_authenticated:
|
||||
@@ -356,33 +352,40 @@ 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():
|
||||
if self.can_manage() or self.level > source.level:
|
||||
return False
|
||||
#if source.profile('moyenne'):
|
||||
# return False
|
||||
return True
|
||||
# BLOCK this user from SOURCE
|
||||
def make_block(self, source, full=False):
|
||||
if find_block(source, self):
|
||||
return False
|
||||
return UserBlock.objects.create(source=source, target=self, full=full)
|
||||
def get_posts(self, limit=50, offset=0, request=None):
|
||||
def make_block(self, source):
|
||||
# trailing
|
||||
block = UserBlock.find_block(self, source)
|
||||
if block and block.source == source:
|
||||
return block.delete()
|
||||
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 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)
|
||||
posts = self.post_set.select_related('community').select_related('creator').annotate(num_yeahs=Count('yeah', distinct=True), num_comments=Count('comment', distinct=True), yeah_given=Exists(has_yeah, distinct=True)).filter().order_by('-created')[offset:offset + limit]
|
||||
posts = self.post_set.select_related('community').select_related('creator').annotate(num_yeahs=Count('yeah', distinct=True), num_comments=Count('comment', distinct=True), yeah_given=Exists(has_yeah, distinct=True)).filter(created__lte=offset_time).order_by('-created')[offset:offset + limit]
|
||||
else:
|
||||
posts = self.post_set.select_related('community').select_related('creator').annotate(num_yeahs=Count('yeah', distinct=True), num_comments=Count('comment', distinct=True)).filter().order_by('-created').exclude(community__require_auth=True)[offset:offset + limit]
|
||||
posts = self.post_set.select_related('community').select_related('creator').annotate(num_yeahs=Count('yeah', distinct=True), num_comments=Count('comment', distinct=True)).filter(created__lte=offset_time).order_by('-created').exclude(community__require_auth=True)[offset:offset + limit]
|
||||
if request:
|
||||
for post in posts:
|
||||
post.setup(request)
|
||||
post.recent_comment = post.recent_comment()
|
||||
return posts
|
||||
def get_comments(self, limit=50, offset=0, request=None):
|
||||
def get_comments(self, limit, offset, request, offset_time):
|
||||
if request.user.is_authenticated:
|
||||
has_yeah = Yeah.objects.filter(comment=OuterRef('id'), by=request.user.id)
|
||||
posts = self.comment_set.select_related('original_post').select_related('creator').select_related('original_post__creator').annotate(num_yeahs=Count('yeah', distinct=True), yeah_given=Exists(has_yeah, distinct=True)).filter().order_by('-created')[offset:offset + limit]
|
||||
posts = self.comment_set.select_related('original_post').select_related('creator').select_related('original_post__creator').annotate(num_yeahs=Count('yeah', distinct=True), yeah_given=Exists(has_yeah, distinct=True)).filter(created__lte=offset_time).order_by('-created')[offset:offset + limit]
|
||||
else:
|
||||
posts = self.comment_set.select_related('original_post').select_related('original_post__creator').select_related('creator').annotate(num_yeahs=Count('yeah', distinct=True)).filter().order_by('-created').exclude(original_post__community__require_auth=True)[offset:offset + limit]
|
||||
posts = self.comment_set.select_related('original_post').select_related('original_post__creator').select_related('creator').annotate(num_yeahs=Count('yeah', distinct=True)).filter(created__lte=offset_time).order_by('-created').exclude(original_post__community__require_auth=True)[offset:offset + limit]
|
||||
if request:
|
||||
for post in posts:
|
||||
post.setup(request)
|
||||
@@ -674,22 +677,32 @@ class Community(models.Model):
|
||||
6: 'xbox',
|
||||
7: 'ps',
|
||||
}.get(self.platform)
|
||||
if thing == "":
|
||||
if not thing:
|
||||
return None
|
||||
return "img/platform-tag-" + thing + ".png"
|
||||
def is_activity(self):
|
||||
return self.tags == 'activity'
|
||||
def clickable(self):
|
||||
return not self.is_activity() and not self.type == 4
|
||||
def get_posts(self, limit=50, offset=0, request=None, favorite=False):
|
||||
# have yet to see a usage of this without all of these params so sure, offset_time is default
|
||||
#def get_posts(self, limit=50, offset=0, request=None, favorite=False):
|
||||
def get_posts(self, limit, offset, request, offset_time):
|
||||
if request.user.is_authenticated:
|
||||
# get users who blocked you
|
||||
blocked_me = request.user.block_target.filter().values('source')
|
||||
|
||||
has_yeah = Yeah.objects.filter(post=OuterRef('id'), by=request.user.id)
|
||||
posts = Post.objects.select_related('creator').annotate(num_yeahs=Count('yeah', distinct=True), num_comments=Count('comment', distinct=True), yeah_given=Exists(has_yeah, distinct=True)).filter(community_id=self.id).order_by('-created')[offset:offset + limit]
|
||||
posts = Post.objects.select_related('creator').annotate(num_yeahs=Count('yeah', distinct=True), num_comments=Count('comment', distinct=True), yeah_given=Exists(has_yeah, distinct=True)
|
||||
).exclude(creator__id__in=Subquery(blocked_me)).filter(community_id=self.id, created__lte=offset_time).order_by('-created')[offset:offset + limit]
|
||||
else:
|
||||
posts = Post.objects.select_related('creator').annotate(num_yeahs=Count('yeah', distinct=True), num_comments=Count('comment', distinct=True)).filter(community_id=self.id).order_by('-created').exclude(community__require_auth=True)[offset:offset + limit]
|
||||
posts = Post.objects.select_related('creator').annotate(num_yeahs=Count('yeah', distinct=True), num_comments=Count('comment', distinct=True)).filter(community_id=self.id, created__lte=offset_time).order_by('-created').exclude(community__require_auth=True)[offset:offset + limit]
|
||||
if request:
|
||||
for post in posts:
|
||||
post.setup(request)
|
||||
# THE TRUE METHOD
|
||||
if request.user.is_authenticated:
|
||||
post.user_is_blocked = UserBlock.find_block(post.creator, request.user)
|
||||
#print(str(post) + ' to ' + str(self.creator) + ':' + str(post.user_is_blocked))
|
||||
post.recent_comment = post.recent_comment()
|
||||
return posts
|
||||
def post_perm(self, request):
|
||||
@@ -740,8 +753,8 @@ class Community(models.Model):
|
||||
if not limit is False and not limit > 0:
|
||||
return 8
|
||||
del(limit)
|
||||
if Post.real.filter(Q(creator=request.user) | Q(creator__addr=request.user.addr), created__gt=timezone.now() - timedelta(seconds=10)).exists():
|
||||
return 3
|
||||
#if Post.real.filter(Q(creator=request.user) | Q(creator__addr=request.user.addr), created__gt=timezone.now() - timedelta(seconds=10)).exists():
|
||||
# return 3
|
||||
if request.POST.get('url'):
|
||||
try:
|
||||
URLValidator()(value=request.POST['url'])
|
||||
@@ -755,6 +768,7 @@ class Community(models.Model):
|
||||
return 1
|
||||
upload = None
|
||||
drawing = None
|
||||
body = request.POST.get('body')
|
||||
if request.FILES.get('screen'):
|
||||
upload = util.image_upload(request.FILES['screen'], True)
|
||||
if upload == 1:
|
||||
@@ -766,9 +780,14 @@ class Community(models.Model):
|
||||
if drawing == 1:
|
||||
return 2
|
||||
# Check for spam using our OWN ALGO!!!!!!!!!
|
||||
if request.user.has_postspam(request.POST.get('body'), upload, drawing):
|
||||
if request.user.has_postspam(body, upload, drawing):
|
||||
return 7
|
||||
new_post = self.post_set.create(body=request.POST.get('body'), creator=request.user, community=self, feeling=int(request.POST.get('feeling_id', 0)), spoils=bool(request.POST.get('is_spoiler')), screenshot=upload, drawing=drawing, url=request.POST.get('url'))
|
||||
for keyword in ['faggot', 'fag', 'nigger', 'nigga', 'hitler']:
|
||||
if keyword in body.lower():
|
||||
return 9
|
||||
if body.isspace() and not drawing:
|
||||
return 10
|
||||
new_post = self.post_set.create(body=body, creator=request.user, community=self, feeling=int(request.POST.get('feeling_id', 0)), spoils=bool(request.POST.get('is_spoiler')), screenshot=upload, drawing=drawing, url=request.POST.get('url'))
|
||||
new_post.is_mine = True
|
||||
return new_post
|
||||
|
||||
@@ -781,18 +800,6 @@ class Community(models.Model):
|
||||
class Meta:
|
||||
verbose_name_plural = "communities"
|
||||
|
||||
# Links between communities for "related" communities
|
||||
class CommunityClink(models.Model):
|
||||
# root/also order doesn't matter, time does though
|
||||
root = models.ForeignKey(Community, related_name='one', on_delete=models.CASCADE)
|
||||
also = models.ForeignKey(Community, related_name='two', on_delete=models.CASCADE)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
# type: related (f) / sub (t)
|
||||
kind = models.BooleanField(default=False)
|
||||
|
||||
objects = CommunityFavoriteManager()
|
||||
|
||||
# Do this, or not
|
||||
class CommunityFavorite(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
by = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
@@ -876,12 +883,13 @@ class Post(models.Model):
|
||||
else:
|
||||
return False
|
||||
def can_yeah(self, request):
|
||||
if request.user.is_authenticated:
|
||||
#if UserBlock.find_block(self.creator, request.user):
|
||||
# return False
|
||||
return True
|
||||
else:
|
||||
if not request.user.is_authenticated or not request.user.is_active():
|
||||
return False
|
||||
# why did cedar-django do this? god knows
|
||||
#return True
|
||||
if self.is_mine(request.user) or UserBlock.find_block(self.creator, request.user):
|
||||
return False
|
||||
return True
|
||||
def can_rm(self, request):
|
||||
if self.creator.has_authority(request.user):
|
||||
return False
|
||||
@@ -909,25 +917,28 @@ class Post(models.Model):
|
||||
# TODO: Make this so that if a post's comments exceeds 100, make the user able to close the comments section
|
||||
if self.number_comments() > 500:
|
||||
return False
|
||||
#if UserBlock.find_block(self.creator, request.user):
|
||||
# return False
|
||||
if UserBlock.find_block(self.creator, request.user):
|
||||
return False
|
||||
return True
|
||||
def get_comments(self, request=None, limit=0, offset=0):
|
||||
if request.user.is_authenticated:
|
||||
blocked_me = request.user.block_target.filter().values('source')
|
||||
|
||||
has_yeah = Yeah.objects.filter(comment=OuterRef('id'), by=request.user.id)
|
||||
comments_pre = self.comment_set.select_related('creator').annotate(num_yeahs=Count('yeah'), yeah_given=Exists(has_yeah)
|
||||
).exclude(creator__id__in=Subquery(blocked_me)).filter(original_post=self).order_by('created')
|
||||
comments = comments_pre
|
||||
if limit:
|
||||
comments = self.comment_set.select_related('creator').annotate(num_yeahs=Count('yeah'), yeah_given=Exists(has_yeah)).filter(original_post=self).order_by('created')[offset:offset + limit]
|
||||
comments = comments_pre[offset:offset + limit]
|
||||
elif offset:
|
||||
comments = self.comment_set.select_related('creator').annotate(num_yeahs=Count('yeah'), yeah_given=Exists(has_yeah)).filter(original_post=self).order_by('created')[offset:]
|
||||
else:
|
||||
comments = self.comment_set.select_related('creator').annotate(num_yeahs=Count('yeah'), yeah_given=Exists(has_yeah)).filter(original_post=self).order_by('created')
|
||||
comments = comments_pre[offset:]
|
||||
else:
|
||||
comments_pre = self.comment_set.select_related('creator').annotate(num_yeahs=Count('yeah')).filter(original_post=self).order_by('created').exclude(original_post__community__require_auth=True)
|
||||
comments = comments_pre
|
||||
if limit:
|
||||
comments = self.comment_set.select_related('creator').annotate(num_yeahs=Count('yeah')).filter(original_post=self).order_by('created').exclude(original_post__community__require_auth=True)[offset:offset + limit]
|
||||
comments = comments_pre[offset:offset + limit]
|
||||
elif offset:
|
||||
comments = self.comment_set.select_related('creator').annotate(num_yeahs=Count('yeah')).filter(original_post=self).order_by('created').exclude(original_post__community__require_auth=True)[offset:]
|
||||
else:
|
||||
comments = self.comment_set.select_related('creator').annotate(num_yeahs=Count('yeah')).filter(original_post=self).order_by('created').exclude(original_post__community__require_auth=True)
|
||||
comments = comments_pre[offset:]
|
||||
if request:
|
||||
for post in comments:
|
||||
post.setup(request)
|
||||
@@ -1029,9 +1040,6 @@ class Post(models.Model):
|
||||
self.has_yeah = self.has_yeah(request)
|
||||
self.can_yeah = self.can_yeah(request)
|
||||
self.is_mine = self.is_mine(request.user)
|
||||
|
||||
|
||||
|
||||
def max_yeahs():
|
||||
try:
|
||||
max_yeahs_post = Post.objects.annotate(num_yeahs=Count('yeah')).aggregate(max_yeahs=Max('num_yeahs'))['max_yeahs']
|
||||
@@ -1090,18 +1098,16 @@ class Comment(models.Model):
|
||||
else:
|
||||
return False
|
||||
def can_yeah(self, request):
|
||||
if request.user.is_authenticated:
|
||||
return True
|
||||
else:
|
||||
if not request.user.is_authenticated or not request.user.is_active():
|
||||
return False
|
||||
#if UserBlock.find_block(self.creator, request.user):
|
||||
# return False
|
||||
if self.is_mine(request.user) or UserBlock.find_block(self.creator, request.user):
|
||||
return False
|
||||
return True
|
||||
def can_rm(self, request):
|
||||
if self.creator.has_authority(request.user):
|
||||
return False
|
||||
#if self.original_post.is_mine(request.user):
|
||||
# return True
|
||||
# if the creator of the post does not have authority, you can remove it.
|
||||
if not self.creator.has_authority(request.user):
|
||||
return True
|
||||
return False
|
||||
def give_yeah(self, request):
|
||||
if not request.user.has_freedom() and Yeah.objects.filter(by=request.user, created__gt=timezone.now() - timedelta(seconds=5)).exists():
|
||||
return False
|
||||
@@ -1207,7 +1213,6 @@ class Profile(models.Model):
|
||||
let_freedom = models.BooleanField(default=True)
|
||||
# Todo: When you see this, implement it; make it a bool that determines whether the user should be able to edit their avatar; if this is true and
|
||||
#let_avatar = models.BooleanField(default=False)
|
||||
adopted = models.ForeignKey(User, null=True, blank=True, related_name='children', on_delete=models.CASCADE)
|
||||
# Post limit, 0 for none
|
||||
limit_post = models.SmallIntegerField(default=0)
|
||||
# If this is true, the user can't change their avatar or nickname
|
||||
@@ -1270,6 +1275,14 @@ class Profile(models.Model):
|
||||
self.origin_id_public = self.origin_id_public(request.user)
|
||||
self.yeahs_visible = self.yeahs_visible(request.user)
|
||||
self.comments_visible = self.comments_visible(request.user)
|
||||
if request.user.is_authenticated and request.user != self.user:
|
||||
# these aren't on the user object so arguably these should not be here
|
||||
# but at this point i do not care just throw away this whole codebase please
|
||||
self.can_follow = self.user.can_follow(request.user)
|
||||
self.can_block = self.user.can_block(request.user)
|
||||
# we will use hasattr
|
||||
if UserBlock.objects.filter(source=request.user, target=self.user).exists():
|
||||
self.is_blocked = True
|
||||
|
||||
class Follow(models.Model):
|
||||
# Todo: remove this
|
||||
@@ -1295,6 +1308,7 @@ class Notification(models.Model):
|
||||
(2, 'Comment on my post'),
|
||||
(3, 'Comment on others\' post'),
|
||||
(4, 'Follow to me'),
|
||||
(5, 'New Announcement'),
|
||||
))
|
||||
merges = models.TextField(blank=True, default='')
|
||||
context_post = models.ForeignKey(Post, null=True, blank=True, on_delete=models.CASCADE)
|
||||
@@ -1633,18 +1647,6 @@ class PollVote(models.Model):
|
||||
#def choice_votes(self):
|
||||
# return PollVote.objects.filter(poll=self.poll, choice=self.choice).count()
|
||||
|
||||
class RedFlag(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
post = models.ForeignKey(Post, blank=True, null=True, on_delete=models.CASCADE)
|
||||
comment = models.ForeignKey(Comment, blank=True, null=True, on_delete=models.CASCADE)
|
||||
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
|
||||
type = models.SmallIntegerField(choices=((0, 'Post'), (1, 'Comment'), (2, 'User'), ))
|
||||
reason = models.SmallIntegerField(choices=((0, "Actual harassment"), (1, "Spam"), (2, "I don't like this"), (3, "Personal info"), (4, "Obscene use of swearing"), (5, "NSFW where not allowed"), (6, "Overly advertising/spam"), (7, "Please delete this")))
|
||||
reasoning = models.TextField(default='', null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return "Report on a " + self.get_type_display() + " for " + self.get_reason_display() + ": " + str(self.reasoning)
|
||||
|
||||
# Login attempts:
|
||||
class LoginAttempt(models.Model):
|
||||
@@ -1665,15 +1667,6 @@ class MetaViews(models.Model):
|
||||
from_user = models.ForeignKey(User, related_name='from_user', on_delete=models.CASCADE)
|
||||
def __str__(self):
|
||||
return str(self.from_user) + ' viewed ' + str(self.target_user)
|
||||
# Fun
|
||||
class ThermostatTouch(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
who = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
|
||||
lvl = models.IntegerField(default=1)
|
||||
|
||||
def __str__(self):
|
||||
return str(created) + " touched the thermostat, setting it to " + str(lvl) + " degrees celsius"
|
||||
|
||||
# Finally
|
||||
class UserBlock(models.Model):
|
||||
@@ -1681,16 +1674,25 @@ class UserBlock(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
source = models.ForeignKey(User, related_name='block_source', on_delete=models.CASCADE)
|
||||
target = models.ForeignKey(User, related_name='block_target', on_delete=models.CASCADE)
|
||||
full = models.BooleanField(default=False)
|
||||
# ...???
|
||||
#full = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return "Block created from " + str(self.source) + " to " + str(self.target)
|
||||
|
||||
@staticmethod
|
||||
def find_block(first, second, full=False):
|
||||
if full:
|
||||
return UserBlock.objects.filter(Q(source=first, full=True) & Q(target=second, full=True) | Q(target=first, full=True) & Q(source=second, full=True)).exists()
|
||||
return UserBlock.objects.filter(Q(source=first) & Q(target=second) | Q(target=first) & Q(source=second)).exists()
|
||||
def find_block(first, second):
|
||||
#, full=False):
|
||||
# in every instance of find_block that I have seen, the second argument is always the request user
|
||||
# so in the interest of making this implementation easy (forgot where the checks are supposed to go otherwise)
|
||||
if not second.is_authenticated:
|
||||
return False
|
||||
#if full:
|
||||
# return UserBlock.objects.filter(Q(source=first, full=full) & Q(target=second, full=full) | Q(target=first, full=full) & Q(source=second, full=full)).exists()
|
||||
block = UserBlock.objects.filter(Q(source=first) & Q(target=second) | Q(target=first) & Q(source=second))
|
||||
if not block.exists():
|
||||
return False
|
||||
return block.first()
|
||||
|
||||
class AuditLog(models.Model):
|
||||
id = models.AutoField(primary_key=True)
|
||||
@@ -1767,7 +1769,7 @@ class ProfileHistory(models.Model):
|
||||
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
|
||||
old_nickname = models.CharField(max_length=64, blank=True, null=True)
|
||||
new_nickname = models.CharField(max_length=64, blank=True, null=True)
|
||||
old_comment = models.TextField(blank=True)
|
||||
old_comment = models.TextField(blank=True, null=True)
|
||||
new_comment = models.TextField(blank=True)
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<h2>What can I do with my own community?</h2>
|
||||
<p>You can edit it, and that's basically it.</p>
|
||||
<h2>What are C-Tokens, and how do I get them?</h2>
|
||||
<p>Community tokens are a stupid and overcomplicated method of preventing 200,000 communities from being made by one person. You get one when signing up, and you can use it to make your own community. You'll have to ask a staff member for more C-Tokens if you want to make more communities. </p>
|
||||
<p>Community tokens are a stupid and overcomplicated method of preventing 200,000 communities from being made by one person. You get one when signing up, and you can use it to make your own community. Please do not ask staff for more C-Tokens unless you believe the communities you are going to make are really that good.</p>
|
||||
<h2>Any future plans?</h2>
|
||||
<p>Fuck, I got no clue. Maybe I should make C-Tokens tradable, or make a community ban system, so you can block people from posting and commenting in your own communities.</p>
|
||||
<p>no</p>
|
||||
</div>
|
||||
{% 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 %}
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
{% post_form request.user community %}
|
||||
{% endif %}
|
||||
<div class="body-content" id="community-post-list">
|
||||
{% post_list posts next %}
|
||||
{% post_list posts next 0 '' time %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{% load closedverse_user %}{% if profile.can_block %}
|
||||
<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 %}">
|
||||
<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">
|
||||
<input type="submit" value="Yes" class="post-button black-button">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -1,6 +1,7 @@
|
||||
{% load closedverse_community %}<form id="reply-form" class="for-identified-user" method="post" action="{% url "main:post-comments" post.id %}">
|
||||
{% load closedverse_community %}
|
||||
{% if user.is_active %}
|
||||
<form id="reply-form" class="for-identified-user" method="post" action="{% url "main:post-comments" post.id %}">
|
||||
{% csrf_token %}
|
||||
{% if user.is_active %}
|
||||
{% if not user.limit_remaining is False %}
|
||||
<div class="post-count-container">
|
||||
<span>Remaining posts for today</span>
|
||||
@@ -42,8 +43,6 @@
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<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="">
|
||||
</div>
|
||||
@@ -51,5 +50,5 @@
|
||||
{% endif %}
|
||||
|
||||
{% if not user.is_active %}
|
||||
<p>Your account has been disabled.</p>
|
||||
<p class="center">Your account has been disabled.</p>
|
||||
{% endif %}
|
||||
@@ -1,5 +1,5 @@
|
||||
{% if not post.is_rm %}
|
||||
{% load closedverse_tags %}<div id="{{ post.unique_id }}" {% if post.spoils 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 or not post.creator.is_active %} hidden test-hidden{% endif %}{% if type == 2 %} post-list-outline{% endif %}" tabindex="0">
|
||||
{% 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">
|
||||
{% if with_community_container %}
|
||||
<p class="community-container">
|
||||
{% if post.is_reply %}
|
||||
@@ -56,6 +56,10 @@
|
||||
{% endif %}
|
||||
<button type="button" class="hidden-content-button">View Anyway</button>
|
||||
</p></div>
|
||||
{% elif post.user_is_blocked %}
|
||||
<div class="hidden-content"><p>Content hidden because you've blocked this user.</p>
|
||||
<button type="button" class="hidden-content-button">View Anyway</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="post-meta">
|
||||
<button type="button" {% if not post.can_yeah %}disabled{% endif %} class="symbol submit yeah-button
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
-->
|
||||
<label class="file-button-container">
|
||||
<span class="input-label">Image <span id="image-dimensions">PNG, JPG, JPEG and GIF are allowed.</span></span>
|
||||
<span class="input-label">Image <span id="image-dimensions">PNG and JPEG are allowed.</span></span>
|
||||
<span class="button file-upload-button">Upload</span>
|
||||
<input accept="image/gif, image/png, image/jpeg, image/jpg, image/svg+xml, image/bmp" type="file" style="display: none;" id="upload-file">
|
||||
<input type="hidden" id="upload-input" name="screen">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{% load closedverse_community %}<form id="post-form" method="post" action="{% url "main:messages-view" friend.username %}" class="folded">
|
||||
{% csrf_token %}
|
||||
{% load closedverse_community %}
|
||||
{% if user.is_active %}
|
||||
<form id="post-form" method="post" action="{% url "main:messages-view" friend.username %}" class="folded">
|
||||
{% csrf_token %}
|
||||
{% feeling_selector %}
|
||||
<div class="textarea-with-menu active-text">
|
||||
<menu class="textarea-menu">
|
||||
@@ -37,5 +38,5 @@
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if not user.is_active %}
|
||||
<p>Your account has been disabled.</p>
|
||||
<p class="center">Your account has been disabled.</p>
|
||||
{% endif %}
|
||||
@@ -1,4 +1,4 @@
|
||||
{% if not comment.is_rm %}{% load closedverse_tags %}<li id="{{ comment.unique_id }}" {% if comment.spoils 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 or not comment.creator.is_active %} hidden{% endif %} trigger">
|
||||
{% 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">
|
||||
{% user_icon_container comment.creator comment.feeling %}
|
||||
<div class="body">
|
||||
<div class="header">
|
||||
@@ -9,7 +9,7 @@
|
||||
<p class="timestamp-container">
|
||||
<a class="timestamp" {% if comment.spoils and not comment.is_mine %}data-href-hidden{% else %}href{% endif %}="{% url "main:comment-view" comment.id %}">{% time comment.created %}</a>
|
||||
{% if comment.drawing %}
|
||||
<span class="spoiler">(drawing)</span>
|
||||
<span class="spoiler">(handwritten)</span>
|
||||
{% endif %}
|
||||
{% if comment.has_edit %}
|
||||
<span class="spoiler">· Edited</span>
|
||||
@@ -26,7 +26,7 @@
|
||||
{% if comment.screenshot %}
|
||||
<div class="screenshot-container still-image"><img src="{{ comment.screenshot }}"></div>
|
||||
{% endif %}
|
||||
{% if comment.spoils and comment.creator.is_active %}
|
||||
{% if comment.spoils and not comment.is_mine and comment.creator.is_active %}
|
||||
<div class="hidden-content"><p>This comment contains spoilers.</p>
|
||||
<button type="button" class="hidden-content-button">View Comment</button>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{% 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">
|
||||
{% load closedverse_community %}
|
||||
{% if user.is_active %}
|
||||
<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 user.is_active %}
|
||||
{% if not user.limit_remaining is False %}
|
||||
<div class="post-count-container">
|
||||
<span>Remaining posts for today</span>
|
||||
@@ -65,5 +66,5 @@
|
||||
{% endif %}
|
||||
|
||||
{% if not user.is_active %}
|
||||
<p>Your account has been disabled.</p>
|
||||
<p class="center">Your account has been disabled.</p>
|
||||
{% endif %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% load closedverse_tags %}{% load closedverse_community %}<div class="list post-list js-post-list" data-next-page-url="{% if next %}?offset={{ next }}{% endif %}">
|
||||
{% load closedverse_tags %}{% load closedverse_community %}<div class="list post-list js-post-list" data-next-page-url="{% if next %}?offset={{ next }}{% if time %}&offset_time={{ time|urlencode }}{% endif %}{% endif %}">
|
||||
{% if posts %}
|
||||
{% for post in posts %}
|
||||
{% community_post post type %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% load closedverse_tags %}<div id="{{ post.unique_id }}" {% if post.spoils or not post.creator.is_active %}data-href-hidden{% else %}data-href{% endif %}="{% url "main:post-view" post.id %}" class="post trigger{% if post.screenshot %} with-image{% endif %}{% if post.spoils or not post.creator.is_active %} hidden test-hidden{% endif %}" tabindex="0">
|
||||
{% 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 %}="{% url "main:post-view" post.id %}" class="post trigger{% if post.screenshot %} with-image{% endif %}{% if post.spoils and not post.is_mine or not post.creator.is_active %} hidden test-hidden{% endif %}" tabindex="0">
|
||||
|
||||
<p class="community-container"><a {% if post.community.clickable %}href="{% url "main:community-view" post.community_id %}"{% endif %}><img src="{{ post.community.icon }}" class="community-icon">{{ post.community.name }}</a></p>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<p class="post-content-text">{{ post.body|truncatechars:100|linebreaksbr }}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if post.spoils and post.creator.is_active %}
|
||||
{% if post.spoils and not post.is_mine and post.creator.is_active %}
|
||||
<div class="hidden-content"><p>This post contains spoilers.
|
||||
<button type="button" class="hidden-content-button">View Post</button>
|
||||
</p></div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% load closedverse_tags %}{% load closedverse_user %}<div class="list post-list js-post-list" data-next-page-url="{% if next %}?offset={{ next }}{% endif %}">
|
||||
{% load closedverse_tags %}{% load closedverse_user %}<div class="list post-list js-post-list" data-next-page-url="{% if next %}?offset={{ next }}{% if time %}&offset_time={{ time|urlencode }}{% endif %}{% endif %}">
|
||||
{% if posts %}
|
||||
{% for post in posts %}
|
||||
{% user_post post type %}
|
||||
|
||||
@@ -30,14 +30,16 @@
|
||||
</a>
|
||||
{% endif %}
|
||||
{% user_sidebar_info user profile %}
|
||||
{% if request.user.is_authenticated and not user.is_me %}
|
||||
{% if request.user.is_authenticated and not user.is_me and profile.can_friend or profile.can_follow or request.user.can_manage %}
|
||||
<div class="user-action-content">
|
||||
<div class="toggle-button">
|
||||
{% if profile.can_follow and not user.is_me %}
|
||||
<button type="button" data-action="{% url "main:user-follow" user.username %}" class="follow-button button symbol{% if user.is_following %} none{% endif %}">Follow</button>
|
||||
<button type="button" data-action="{% url "main:user-unfollow" user.username %}" class="unfollow-button button symbol{% if not user.is_following %} none{% endif %}" data-screen-name="{{ user.nickname }}">Follow</button>
|
||||
{% endif %}
|
||||
{% if selection == 0 %}
|
||||
{% if user.friend_state == 0 %}
|
||||
{% if profile.can_friend %}
|
||||
{% if profile.can_friend and not user.is_me %}
|
||||
<button type="button" data-action="{% url "main:user-fr-create" user.username %}" class="friend-button create button symbol">Send friend request</button>
|
||||
{% endif %}
|
||||
{% elif user.friend_state == 1 %}
|
||||
@@ -51,10 +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>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% if fr %}{% fr_accept fr %}{% endif %}
|
||||
{% if user.friend_state == 0 %}
|
||||
<div class="dialog none" data-modal-types="post-friend-request">
|
||||
@@ -64,11 +67,7 @@
|
||||
<div class="window-body">
|
||||
<p class="description">Friend Request: <img width="36px" height="36px" src="{% avatar user %}">{{ user.nickname }}</p>
|
||||
<form method="post">
|
||||
|
||||
|
||||
|
||||
<textarea name="body" class="textarea" maxlength="2200" data-placeholder="Write a friend request here." placeholder="Write a friend request here."></textarea>
|
||||
|
||||
<div class="form-buttons">
|
||||
<input type="button" class="olv-modal-close-button gray-button" value="Cancel">
|
||||
<input type="submit" value="Send" class="post-button black-button">
|
||||
@@ -80,8 +79,10 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% block_modal user profile %}
|
||||
|
||||
</div>
|
||||
{% elif user.is_me and not general %}
|
||||
{% endif %}{% if user.is_me and not general %}
|
||||
<div id="edit-profile-settings"><a class="button symbol" href="{% url "main:profile-settings" %}">Profile Settings</a></div>
|
||||
{% endif %}{% if user.is_me %}
|
||||
<button class="button" onclick="Olv.Closed.lights()">Toggle Dark Mode</button>
|
||||
|
||||
@@ -5,18 +5,16 @@
|
||||
<form method="post">
|
||||
<img src="{% static "img/menu-logo.svg" %}">
|
||||
<p class="lh">Reset password</p>
|
||||
<p>Hello {{ user.username }}, it's time to change your password.</p>
|
||||
<form method="post">
|
||||
<p>Hello {{ 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 %}
|
||||
<p class="red" style="margin-bottom:6px"></p>
|
||||
<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>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -18,79 +18,8 @@
|
||||
<h2 class="label">Active clones</h2>
|
||||
<div id="guide" class="help-content">
|
||||
<div class="faq">
|
||||
<p>im too lazy to update this</p>
|
||||
<!--
|
||||
<h2>Juice</h2>
|
||||
{% if not user.is_staff %}
|
||||
<p>Clone online. - [URL REDACTED]</p>
|
||||
{% endif %}
|
||||
{% if user.is_staff and user.is_authenticated %}
|
||||
<p>Do not share this URL to the public. - [<a href="https://juice.isledelfino.net/">URL</a>]</p>
|
||||
{% endif %}
|
||||
<p>Juice is based off Project Ultima. It's been around for a while, considering how long most clones usually last.</p>
|
||||
<h2>Leaper</h2>
|
||||
{% if not user.is_staff %}
|
||||
<p>Clone online. - [URL REDACTED]</p>
|
||||
{% endif %}
|
||||
{% if user.is_staff and user.is_authenticated %}
|
||||
<p>Do not share this URL to the public. - [<a href="https://caustica.isledelfino.net/">URL</a>]</p>
|
||||
{% endif %}
|
||||
<p>This clone has a few distinct features that separate it from the others. You have a wide selection of (slightly buggy) themes. You have background music for some pages. And you can edit your post too.</p>
|
||||
<h2>"Miiverse" Clone</h2>
|
||||
<p>Clone online. - [<a href="https://miiverse.lol">miiverse.lol</a>]</p>
|
||||
<p>It's your standard Cedar rehost, it's skinned to fit a "Miiverse" aesthetic. For a while this clone remained a secret until some dude leaked the URL. Since the cat was out of the bag a long time ago, I might as well show it here.</p>
|
||||
<h2>Bradenverse xddddd</h2>
|
||||
<p>this clone will last a week, so I don't care.</p>
|
||||
<p>It comes up, dies and comes back online</p>
|
||||
<p>i forgor 💀 the url</p>
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="label">Active public clones</h2>
|
||||
<div id="guide" class="help-content">
|
||||
<div class="faq">
|
||||
<h2>Cedar</h2>
|
||||
<p>You're using this one right now!</p>
|
||||
<p>This site is not super expensive, and I'm able to reasonably maintain this site. Now this is not happening anytime soon, but eventually Cedar will be shut down. Users will be informed of the upcoming shutdown in advance when that time comes. All user data like profiles, posts, comments, and conversations will all be deleted and not archived by me.</p>
|
||||
<h2>Exverse</h2>
|
||||
<p>Clone online, but who fucking cares? - [<a href="https://exverse.ml/">https://exverse.ml/</a>]</p>
|
||||
<p>Also, I can't sign up to it for whatever reason, don't ask why I want to, but yeah it's a bit broken I guess.</p>
|
||||
<p>Edit: so I did sign up for that site, it's busted as fuck, the CSS looks HORRIBLE oh god what the fuck</p>
|
||||
<p>The entire site is ugly as fuck, I don't know what the dude messing with the CSS was smoking.</p>
|
||||
<h2>Rverse</h2>
|
||||
<p>Clone online. - [3DS ONLY]</p>
|
||||
<p>Does this even count?</p>
|
||||
<p>Well, it's the most active clone out there, the only problem is that it's only accessible through a hacked 3DS system with Rverse installed. For some, this may be a dealbreaker.</p>
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="label">Other clones</h2>
|
||||
<div id="guide" class="help-content">
|
||||
<div class="faq">
|
||||
<p>Goofy ahh clones</p>
|
||||
<h2 style="background-color: #000000;">Geoverse</h2>
|
||||
<p>This service has ended. - [<a href="http://geoverse.usecedar.ca/">http://geoverse.usecedar.ca/</a>]</p>
|
||||
<h3>What the hell happened to it?</h3>
|
||||
<p>I have a lot of stuff to explain here. Let's just go in chronological order.</p>
|
||||
<ul>
|
||||
<li>I hosted this clone for Ghosty Tongue.</li>
|
||||
<li>A while passes by with zero activity.</li>
|
||||
<li>I announce its shutdown date on the site itself.</li>
|
||||
<li>Ghosty decides to give out the SSH password to a few people.</li>
|
||||
<li>Ghosty claims he had permission from me to do this, but he lied.</li>
|
||||
<li>Ghosty posts the SSH login on the announcements channel for the Clonepedia Discord server.</li>
|
||||
<li>So basically the database is now fully accessible, emails, and IPs are free real estate.</li>
|
||||
<li>The discord goes fucking berserk.</li>
|
||||
<li>HTML elements are being edited.</li>
|
||||
<li>I wake up to 1000 pings on people warning me about the compromised server.</li>
|
||||
<li>I look at the hellhole that's Geoverse.</li>
|
||||
<li>I shut it down.</li>
|
||||
<li>I revive it shorty after with a new SSH password.</li>
|
||||
<li>I turn that shit into fucking Minionsverse.</li>
|
||||
<li>I shut it down forever this time.</li>
|
||||
</ul>
|
||||
<h2>Banama</h2>
|
||||
<p>Clone online. - [<a href="https://banama.club">https://banama.club</a>]</p>
|
||||
<p>Now, none of us are getting in, but let's think of this website as a place to accommodate a friend group more than a regular clone. It's nothing all that spectacular.</p>
|
||||
-->
|
||||
<h1>this clone</h1>
|
||||
<p>uhh uhh youre using it now and its good enough</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{% user_sidebar request user user.profile 0 True %}
|
||||
<div class="main-column" id="help">
|
||||
<div class="post-list-outline">
|
||||
<h2 class="label">Contact the team behind this</h2>
|
||||
<h2 class="label">Where even do I contact you, anyway?</h2>
|
||||
<div id="guide" class="help-content">
|
||||
<div class="faq">
|
||||
<p>I'll make this page later, need permission from our admins and shit...</p>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Hi</title>
|
||||
<meta charset="UTF-8">
|
||||
<style>html{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto, Helvetica, Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";}</style>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{% extends "closedverse_main/layout.html" %}
|
||||
{% load static %}{% block main-body %}
|
||||
<div class="main-column center">
|
||||
<div class="post-list-outline login-page">
|
||||
<form method="post">
|
||||
<img src="{% static "img/menu-logo.png" %}">
|
||||
<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">
|
||||
<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_again" class="auth-input" name="password" placeholder="Password again" required></label></h3>
|
||||
{% csrf_token %}
|
||||
<p class="red" style="margin-bottom:6px"></p>
|
||||
<button type="submit" class="button">Reset</button>
|
||||
|
||||
</form>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -16,7 +16,7 @@
|
||||
<h2>I'm getting "Your password must be reset"?</h2>
|
||||
<p>This means that your password must be reset. Reset it via email, or ask an admin to reset it. In most cases, an admin has emailed you a password reset link.</p>
|
||||
|
||||
<h2>I'm being hacked! HELP!!!</h2>
|
||||
<h2>i"m bEinG hAcKeD!!!!!!!!!!</h2>
|
||||
<p>If others are in your account, no worry, when you change your password, everyone gets logged out.<br>
|
||||
Unless your email was changed or you don't have one, in that case, contact an admin and they will help you ASAP.
|
||||
<br><br>You should use a random password and keep it in your notes or something. In most cases, public user accounts are made due to one character passwords. Please do not use one character passwords.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{% user_sidebar request user user.profile 0 True %}
|
||||
<div class="main-column" id="help">
|
||||
<div class="post-list-outline">
|
||||
<h2 class="label">Cedar stats</h2>
|
||||
<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>
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
{% user_sidebar request user user.profile 0 True %}
|
||||
<div class="main-column" id="help">
|
||||
<div class="post-list-outline">
|
||||
<h2 class="label">Why?</h2>
|
||||
<h2 class="label">Why should I join?</h2>
|
||||
<div id="guide" class="help-content">
|
||||
<p>why should you join?</p>
|
||||
<div class="faq">
|
||||
<h2>Why should I join ?</h2>
|
||||
<ul>
|
||||
<li>I don't know...</li>
|
||||
</ul>
|
||||
<h2>because i said so.</h2>
|
||||
<p><small>you don't have to though</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
{% endif %}
|
||||
{% if not allow_signups %}
|
||||
<div class="ll">
|
||||
<p>Signing up is disabled for now, check by later.</p>
|
||||
<p>Signing up is disabled for now, check back later.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="tab2">
|
||||
<a class="tab-icon-my-news selected" href="{% url "main:notifications" %}">
|
||||
<span class="symbol nf"></span>
|
||||
<span>Notifications</span>
|
||||
<span>Updates</span>
|
||||
</a>
|
||||
|
||||
<a class="tab-icon-my-news{% if frs %} notify{% endif %}" href="{% url "main:friend-requests" %}">
|
||||
|
||||
@@ -129,7 +129,6 @@
|
||||
<p>You must sign in to post a comment.<br><br>Sign in using a Cedar account to make posts and comments, as well as give Yeahs and follow users.</p>
|
||||
<a href="{% url "main:signup" %}" class="arrow-button"><span>Create an account</span></a>
|
||||
<a href="{% url "main:help-faq" %}" class="arrow-button"><span>FAQ/Frequently Asked Questions</span></a>
|
||||
<a href="{% url "main:help-contact" %}" class="arrow-button"><span>Contact Us</span></a>
|
||||
</div>
|
||||
{% elif not post.can_comment %}
|
||||
<div class="cannot-reply"><div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% extends "closedverse_main/layout.html" %}
|
||||
{% block main-body %}{% load closedverse_user %}{% load closedverse_tags %}
|
||||
{% block main-body %}{% load closedverse_user %}{% load closedverse_tags %}{% load closedverse_community %}
|
||||
{% user_sidebar request user profile 0 %}
|
||||
|
||||
<div class="main-column"><div class="post-list-outline">
|
||||
@@ -45,12 +45,13 @@
|
||||
</div>
|
||||
<p class="note">Enter your region here. It'll appear on your profile.
|
||||
<br>
|
||||
<a class="get-ipinfo" href="#">If you want to use your location, you can get it automatically here (it will not be automatically saved).</a>
|
||||
</p>
|
||||
</li>
|
||||
<li class="setting-email">
|
||||
<p class="settings-label">E-mail address</p>
|
||||
<div class="center center-input">
|
||||
<input type="text" name="email" maxlength="255" placeholder="Email address" value="{{ user.email }}">
|
||||
<input type="text" name="email" maxlength="255" placeholder="Email address" value="{{ user.email|default_if_none:"" }}">
|
||||
</div>
|
||||
<p class="note">Please note that your email can be a fake one, however if you need to reset your password, this must be accessible. You can't share emails.</p>
|
||||
{% if user.email %}
|
||||
@@ -90,10 +91,10 @@
|
||||
<li class="setting-color">
|
||||
<p class="settings-label">Nickname color</p>
|
||||
<div class="center center-input">
|
||||
<input type="hidden" name="color" maxlength="7" placeholder="Enter a hex color value here" value="{{ user.color }}">
|
||||
<input type="hidden" name="color" maxlength="7" placeholder="Enter a hex color value here" value="{{ user.color|default_if_none:"" }}">
|
||||
<button class="button color-thing">Open color picker</button>
|
||||
</div>
|
||||
<p class="note">This is the color your nickname will appear as. Leave it blank for the default. It will appear like so.</p>
|
||||
<p class="note">This is the color your nickname will appear as. Set it to white (#ffffff) and it will return to the default. It will appear like so.</p>
|
||||
{% user_sidebar_info user %}
|
||||
</li>
|
||||
{% if profile.origin_id %}
|
||||
@@ -191,23 +192,28 @@
|
||||
<p class="error"></p>
|
||||
<p class="note">Enter your Nintendo Network ID here. It'll appear on your profile if you set it to be visible.</p>
|
||||
</li>
|
||||
{% if not user.has_plain_avatar %}
|
||||
<li class="setting-avatar">
|
||||
<div class="icon-container">
|
||||
<img class="icon nnid-icon mii{% if not user.has_mh %} none{% endif %}" src="{% miionly user.mh %}">
|
||||
<img class="icon nnid-icon gravatar{% if user.has_mh %} none{% endif %}" src="{{ user.gravatar }}">
|
||||
<img class="icon nnid-icon gravatar{% if user.has_mh or user.has_plain_avatar %} none{% endif %}" src="{{ user.gravatar }}">
|
||||
{% if user.has_freedom %}
|
||||
<img class="icon nnid-icon custom{% if not user.has_plain_avatar %} none{% endif %}" src="{{ user.do_avatar }}">
|
||||
{% endif %}
|
||||
</div>
|
||||
<p class="settings-label">Do you want the avatar shown beside your content to use the Mii from your Nintendo Network ID or a Gravatar?</p>
|
||||
<p class="settings-label">Do you want the avatar shown beside your content to use the Mii from your Nintendo Network ID or a Gravatar or a custom avatar the way God intended?</p>
|
||||
<label><input type="radio" name="avatar" value="0"{% if user.has_mh %} checked{% endif %}>Mii</label>
|
||||
<label><input type="radio" name="avatar" value="1"{% if not user.has_mh %} checked{% endif %}>Gravatar</label>
|
||||
<p class="note">Selecting the Gravatar option will cause your avatar to be pulled from the <a href="https://gravatar.com">Gravatar account</a> linked to your email address, and feelings won't be shown in your posts unless you choose to use a Mii instead.</p>
|
||||
</li>
|
||||
{% if user.has_freedom %}
|
||||
<label><input type="radio" name="avatar" value="2"{% if user.has_plain_avatar%} checked{% endif %}>Custom</label>
|
||||
<span id="upload-thing"{% if not user.has_plain_avatar %} class="none"{% endif %}>{% file_button %}</span>
|
||||
<style>
|
||||
.setting-avatar div.file-button-container { display: none; }
|
||||
</style>
|
||||
{% else %}
|
||||
<p class="settings-label">It appears that you somehow have a plain URL avatar, change it here (<strong>if you change it to nothing then it will reset to being selectable !!</strong>)</p>
|
||||
<div class="center center-input">
|
||||
<input type="text" name="avatar" maxlength="255" placeholder="Avatar url" value="{{ user.avatar }}">
|
||||
</div>
|
||||
<input type="hidden" name="avatar" value="2">
|
||||
{% endif %}
|
||||
<p class="note">Selecting the Gravatar option will cause your avatar to be pulled from the <a href="https://gravatar.com">Gravatar account</a> linked to your email address, and feelings won't be shown in your posts unless you choose to use a Mii instead. Same with the custom avatar option but who really cared anyway?</p>
|
||||
</li>
|
||||
|
||||
{% csrf_token %}
|
||||
<div class="form-buttons">
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<h3 class="label nnid"><label>Nintendo Network ID: <input type="text" class="auth-input" name="origin_id" maxlength="16" minlength="6" placeholder="NNID" data-mii-domain="{{ mii_domain }}" data-action="{{ mii_endpoint }}">
|
||||
<img class="none">
|
||||
</label></h3>
|
||||
<input type="hidden" name="mh">
|
||||
<h3 class="label"><label><span class="red">%</span> E-mail address: <input type="email" class="auth-input" name="email" maxlength="254" minlength="6" placeholder="Email"></label></h3>
|
||||
<h3 class="label"><label><span class="red">*</span> Password: <input type="password" class="auth-input" name="password" maxlength="32" minlength="6" placeholder="Password"></label></h3>
|
||||
<h3 class="label"><label><span class="red">*</span> Confirm password: <input type="password" class="auth-input" name="password_again" maxlength="32" minlength="6" placeholder="Password again"></label></h3>
|
||||
@@ -21,15 +22,13 @@
|
||||
<div class="g-recaptcha" data-sitekey="{{ recaptcha }}" data-theme="dark"></div>
|
||||
<script src='https://www.google.com/recaptcha/api.js'></script>
|
||||
{% endif %}
|
||||
|
||||
<p class="red" style="margin-bottom:6px"></p>
|
||||
<button type="submit" class="button" onclick="event.preventDefault();cac();">Create account</button>
|
||||
<div class="ll">
|
||||
<p>All fields with a red asterisk (<span class="red">*</span>) are required.</p>
|
||||
<p>NNIDs are only required for getting a Mii and a nickname from.</p>
|
||||
<p>If you do not provide a nickname but provide an NNID, the nickname will be taken from that ID. The ID's nickname, however, is prioritized over the nickname field.</p>
|
||||
<p>You will be able to change your avatar after you sign up.</p>
|
||||
<p><span class="red">%</span>: Emails are not required to sign up, however it is used for Gravatar and account recovery.</p>
|
||||
<p>NNIDs are only required for getting a Mii from.</p>
|
||||
<p>You will be able to change your avatar (or use a custom one) after you sign up.</p>
|
||||
<p><span class="red">%</span>: If you don't fill in your email address, you can't reset your password until you have one.</p>
|
||||
<p><span class="red">$</span>: Your username is used to log in. It'll appear similarly to your NNID on Miiverse, below your nickname.</p>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -0,0 +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 %}
|
||||
{% block_modal user profile %}
|
||||
{% endblock %}
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="main-column"><div class="post-list-outline">
|
||||
<h2 class="label">{{ title }}</h2>
|
||||
|
||||
{% u_post_list posts next 3 %}
|
||||
{% u_post_list posts next 3 '' time %}
|
||||
|
||||
</div></div>
|
||||
{% endblock %}
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="main-column"><div class="post-list-outline">
|
||||
<h2 class="label">{{ title }}</h2>
|
||||
|
||||
{% u_post_list posts next 0 %}
|
||||
{% u_post_list posts next 0 '' time %}
|
||||
|
||||
</div></div>
|
||||
{% endblock %}
|
||||
@@ -34,6 +34,12 @@ def user_sidebar_info(user, profile=None):
|
||||
'user': user,
|
||||
'profile': profile,
|
||||
}
|
||||
@register.inclusion_tag('closedverse_main/elements/block-modal.html')
|
||||
def block_modal(user, profile):
|
||||
return {
|
||||
'user': user,
|
||||
'profile': profile,
|
||||
}
|
||||
@register.inclusion_tag('closedverse_main/elements/fr-accept.html')
|
||||
def fr_accept(fr):
|
||||
return {
|
||||
@@ -48,7 +54,7 @@ def user_post(post, type=0):
|
||||
}
|
||||
|
||||
@register.inclusion_tag('closedverse_main/elements/u-post-list.html')
|
||||
def u_post_list(posts, next_offset=None, type=2, nf_text=''):
|
||||
def u_post_list(posts, next_offset=None, type=2, nf_text='', time=None):
|
||||
text = {
|
||||
0: "This user hasn't made any posts yet.",
|
||||
1: "This user hasn't given a Yeah to any posts yet.",
|
||||
@@ -59,6 +65,7 @@ def u_post_list(posts, next_offset=None, type=2, nf_text=''):
|
||||
'posts': posts,
|
||||
'nf': text,
|
||||
'next': next_offset,
|
||||
'time': time,
|
||||
'type': type,
|
||||
}
|
||||
@register.inclusion_tag('closedverse_main/elements/profile-post.html')
|
||||
|
||||
@@ -41,7 +41,6 @@ urlpatterns = [
|
||||
url(r'users/'+ username +'/tools/set$', views.user_tools_set, name='user-tools-set'),
|
||||
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'),
|
||||
# Communities
|
||||
url(r'communities.search$', views.community_search, name='community-search'),
|
||||
@@ -107,14 +106,9 @@ urlpatterns = [
|
||||
url(r'help/contact/?$', views.help_contact, name='help-contact'),
|
||||
url(r'help/login/?$', views.help_login, name='help-login'),
|
||||
url(r'help/whatads/?$', views.whatads, name='what-ads'),
|
||||
url(r'help/actclones/?$', views.active_clones, name='active-clones'),
|
||||
url(r'help/approval/?$', views.help_approval, name='help-approval'),
|
||||
url(r'why/?$', views.help_why, name='help-why'),
|
||||
|
||||
|
||||
# "API"
|
||||
url(r'posts.json$', views.post_list, name='post-list'),
|
||||
|
||||
# Util, right now we are away from the primary appo
|
||||
url(r'origin$', views.origin_id, name='origin-id-get'),
|
||||
# :^)
|
||||
|
||||
+75
-20
@@ -1,4 +1,3 @@
|
||||
from lxml import html
|
||||
# Todo: move all requests to using requests instead of urllib3
|
||||
import urllib.request, urllib.error
|
||||
import requests
|
||||
@@ -7,6 +6,7 @@ from random import choice
|
||||
import json
|
||||
import time
|
||||
import os.path
|
||||
import random
|
||||
from PIL import Image, ExifTags, ImageFile
|
||||
from datetime import datetime
|
||||
from binascii import crc32
|
||||
@@ -79,13 +79,26 @@ def recaptcha_verify(request, key):
|
||||
return True
|
||||
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||
# This image upload code is fucked now thanks to pillow. I gotta go through it and refine it.
|
||||
def image_upload(img, stream=False, drawing=False):
|
||||
# Decode the image
|
||||
decodedimg = img.read() if stream else base64.b64decode(img)
|
||||
# Open the image
|
||||
def image_upload(img, stream=False, drawing=False, avatar=False):
|
||||
if stream:
|
||||
decodedimg = img.read()
|
||||
else:
|
||||
try:
|
||||
decodedimg = base64.b64decode(img)
|
||||
except ValueError:
|
||||
return 1
|
||||
if stream:
|
||||
if not 'image' in img.content_type:
|
||||
return 1
|
||||
# upload svg?
|
||||
#if 'svg' in mime:
|
||||
#
|
||||
try:
|
||||
im = Image.open(io.BytesIO(decodedimg))
|
||||
# Check for EXIF data and rotate the image if necessary
|
||||
# OSError is probably from invalid images, SyntaxError probably from unsupported images
|
||||
except (OSError, SyntaxError):
|
||||
return 1
|
||||
# Taken from https://coderwall.com/p/nax6gg/fix-jpeg-s-unexpectedly-rotating-when-saved-with-pil
|
||||
if hasattr(im, '_getexif'):
|
||||
orientation = 0x0112
|
||||
exif = im._getexif()
|
||||
@@ -98,29 +111,56 @@ def image_upload(img, stream=False, drawing=False):
|
||||
}
|
||||
if orientation in rotations:
|
||||
im = im.transpose(rotations[orientation])
|
||||
# Resize the image
|
||||
im.thumbnail((800, 800))
|
||||
# Check the aspect ratio if this is a drawing
|
||||
if avatar:
|
||||
# crop 1:1
|
||||
width, height = im.size
|
||||
min_dimension = min(width, height)
|
||||
crop_size = min_dimension
|
||||
left = (width - crop_size) // 2
|
||||
top = (height - crop_size) // 2
|
||||
right = left + crop_size
|
||||
bottom = top + crop_size
|
||||
im = im.crop((left, top, right, bottom))
|
||||
im.thumbnail((256, 256))
|
||||
else:
|
||||
im.thumbnail((1280, 1280))
|
||||
|
||||
# Let's check the aspect ratio and see if it's crazy
|
||||
# IF this is a drawing
|
||||
if drawing and ((im.size[0] / im.size[1]) < 0.30):
|
||||
return 1
|
||||
# Generate a hash of the image
|
||||
|
||||
# I know some people have aneurysms when they see people actually using SHA1 in the real world, for anything in general.
|
||||
# Yes, we are really using it. Sorry if that offends you. It's just fast and I don't feel I need anything more random, since we are talking about IMAGES.
|
||||
if stream:
|
||||
hash = sha1()
|
||||
for chunk in img.chunks():
|
||||
hash.update(chunk)
|
||||
imhash = hash.hexdigest()
|
||||
else:
|
||||
imhash = sha1(im.tobytes()).hexdigest()
|
||||
# Set the file format and location
|
||||
# File saving target
|
||||
target = 'png'
|
||||
if stream:
|
||||
# If we have a stream and either a JPEG or a WEBP, save them as those since those are a bit better than plain PNG
|
||||
if 'jpeg' in img.content_type:
|
||||
target = 'jpeg'
|
||||
im = im.convert('RGB')
|
||||
elif 'webp' in img.content_type:
|
||||
target = 'webp'
|
||||
floc = imhash + '.' + target
|
||||
# Save the file if it doesn't already exist
|
||||
# If the file exists, just use it, that's what hashes are for.
|
||||
if not os.path.exists(settings.MEDIA_ROOT + floc):
|
||||
im.save(settings.MEDIA_ROOT + floc, target, quality=80, method=6)
|
||||
# Return the URL of the file
|
||||
im.save(settings.MEDIA_ROOT + floc, target, optimize=True)
|
||||
return settings.MEDIA_URL + floc
|
||||
|
||||
# Todo: Put this into post/comment delete thingy method
|
||||
def image_rm(image_url):
|
||||
if settings.image_delete_opt:
|
||||
if settings.IMAGE_DELETE_SETTING:
|
||||
if settings.MEDIA_URL in image_url:
|
||||
sysfile = image_url.split(settings.MEDIA_URL)[1]
|
||||
sysloc = settings.MEDIA_ROOT + sysfile
|
||||
if settings.image_delete_opt > 1:
|
||||
if settings.IMAGE_DELETE_SETTING > 1:
|
||||
try:
|
||||
remove(sysloc)
|
||||
except:
|
||||
@@ -155,12 +195,27 @@ def filterchars(str=""):
|
||||
for char in forbid:
|
||||
if char in str:
|
||||
str = str.replace(char, " ")
|
||||
if str.isspace():
|
||||
return 'None'
|
||||
return str
|
||||
|
||||
# Check IP for proxy.
|
||||
""" Not using getipintel anymore
|
||||
def getipintel(addr):
|
||||
# My router's IP prefix is 192.168.1.*, so this works in debug
|
||||
if settings.ipintel_email and not '192.168' in addr:
|
||||
try:
|
||||
site = urllib.request.urlopen('https://check.getipintel.net/check.php?ip={0}&contact={1}&flags=f'
|
||||
.format(addr, settings.ipintel_email))
|
||||
except:
|
||||
return 0
|
||||
return float(site.read().decode())
|
||||
else:
|
||||
return 0
|
||||
"""
|
||||
# Now using iphub
|
||||
def iphub(addr):
|
||||
if settings.iphub_key and not '192.168' in addr:
|
||||
get = requests.get('http://v2.api.iphub.info/ip/' + addr, headers={'X-Key': settings.iphub_key})
|
||||
if settings.IPHUB_KEY and not '192.168' in addr:
|
||||
get = requests.get('http://v2.api.iphub.info/ip/' + addr, headers={'X-Key': settings.IPHUB_KEY})
|
||||
if get.json()['block'] == 1:
|
||||
return True
|
||||
else:
|
||||
|
||||
+132
-73
@@ -20,12 +20,13 @@ from random import getrandbits
|
||||
from random import choice
|
||||
from json import dumps, loads
|
||||
import sys, traceback
|
||||
import base64
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
from django.utils import timezone
|
||||
import django.utils.dateformat
|
||||
from binascii import hexlify
|
||||
from os import urandom
|
||||
from datetime import date
|
||||
|
||||
# client-side mii fetch GET endpoint (like pf2m.com/hash if it supported cors)
|
||||
mii_endpoint = 'https://nnidlt.murilo.eu.org/api.php?output=hash_only&env=production&user_id='
|
||||
@@ -46,6 +47,7 @@ def json_response(msg='', code=0, httperr=400):
|
||||
}
|
||||
return JsonResponse(thing, safe=False, status=httperr)
|
||||
def community_list(request):
|
||||
"""Lists communities / main page."""
|
||||
popularity = Community.popularity
|
||||
obj = Community.objects
|
||||
if request.user.is_authenticated:
|
||||
@@ -189,15 +191,10 @@ def login_page(request):
|
||||
# Now let's authenticate.
|
||||
# Wait, first check if the user exists. Remove spaces from the username, because some people do that.
|
||||
# Hold up, first we need to check proxe.
|
||||
# Never mind
|
||||
"""
|
||||
if settings.PROD:
|
||||
if iphub(request.META['HTTP_CF_CONNECTING_IP']):
|
||||
spamuser = True
|
||||
if settings.disallow_proxy:
|
||||
# This was for me, a server error will email admins of course.
|
||||
raise ValueError
|
||||
"""
|
||||
|
||||
# Uncomment this if you want users to be forbidden from logging in with a proxy.
|
||||
#if settings.CLOSEDVERSE_PROD and settings.DISALLOW_PROXY and iphub(request.META['REMOTE_ADDR']):
|
||||
# return HttpResponseNotFound("The user doesn't exist.")
|
||||
user = User.objects.authenticate(username=request.POST['username'], password=request.POST['password'])
|
||||
# None = doesn't exist, False = invalid password.
|
||||
if user is None:
|
||||
@@ -206,9 +203,9 @@ def login_page(request):
|
||||
# Todo: I might want to do some things relating to making models take care of object stuff like this instead of the view, it's totally messed up now.
|
||||
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('HTTP_CF_CONNECTING_IP'))
|
||||
if user[1] is False:
|
||||
if user[1] == False:
|
||||
return HttpResponse("Invalid password.", status=401)
|
||||
elif user[1] is 2:
|
||||
elif user[1] == 2:
|
||||
return HttpResponse("This account's password needs to be reset. Contact an admin or reset by email.", status=400)
|
||||
elif not user[0].is_active():
|
||||
return HttpResponseForbidden("This account was disabled.")
|
||||
@@ -233,7 +230,12 @@ def login_page(request):
|
||||
def signup_page(request):
|
||||
"""Signup page, lots of checks here"""
|
||||
# Redirect the user to / if they're logged in, forcing them to log out
|
||||
if settings.allow_signups:
|
||||
if not settings.allow_signups:
|
||||
return render(request, 'closedverse_main/signups-blocked.html', {
|
||||
'title': 'Log in',
|
||||
#'classes': ['no-login-btn']
|
||||
})
|
||||
|
||||
if request.user.is_authenticated:
|
||||
return redirect('/')
|
||||
if request.method == 'POST':
|
||||
@@ -255,7 +257,6 @@ def signup_page(request):
|
||||
return HttpResponseBadRequest("The provided invite code does not exist.")
|
||||
if not invite.is_valid():
|
||||
return HttpResponseBadRequest("The provided invite code has been used or is void. Please ask for another code.")
|
||||
|
||||
invited = True
|
||||
|
||||
|
||||
@@ -298,11 +299,8 @@ def signup_page(request):
|
||||
if check_signupban:
|
||||
return HttpResponseBadRequest("Get on your hands and knees")
|
||||
if iphub(request.META['HTTP_CF_CONNECTING_IP']):
|
||||
spamuser = True
|
||||
if settings.disallow_proxy:
|
||||
return HttpResponseBadRequest("You cannot sign up with a proxy.")
|
||||
else:
|
||||
spamuser = True
|
||||
if request.POST['origin_id']:
|
||||
if User.nnid_in_use(request.POST['origin_id']):
|
||||
return HttpResponseBadRequest("That Nintendo Network ID is already in use, that would cause confusion.")
|
||||
@@ -337,11 +335,6 @@ def signup_page(request):
|
||||
'mii_endpoint': mii_endpoint,
|
||||
#'classes': ['no-login-btn'],
|
||||
})
|
||||
else:
|
||||
return render(request, 'closedverse_main/signups-blocked.html', {
|
||||
'title': 'Log in',
|
||||
#'classes': ['no-login-btn']
|
||||
})
|
||||
|
||||
def forgot_passwd(request):
|
||||
"""Password email page / post endpoint."""
|
||||
@@ -382,9 +375,11 @@ def logout_page(request):
|
||||
return redirect(request.GET['next'])
|
||||
return redirect('/')
|
||||
def user_view(request, username):
|
||||
|
||||
"""The user view page, has recent posts/yeahs."""
|
||||
user = get_object_or_404(User, username__iexact=username)
|
||||
# if this user doesn't have a profile then the page won't work anyway
|
||||
#if user.username == "ClosedverseAdmin":
|
||||
# raise Http404()
|
||||
if user.is_me(request):
|
||||
title = 'My profile'
|
||||
else:
|
||||
@@ -393,8 +388,18 @@ def user_view(request, username):
|
||||
title = '{0}\'s profile'.format(user.nickname)
|
||||
profile = user.profile()
|
||||
profile.setup(request)
|
||||
if hasattr(profile, 'is_blocked'):
|
||||
return render(request, 'closedverse_main/user_blocked.html', {
|
||||
'classes': ['profile-top'],
|
||||
'user': user,
|
||||
'profile': profile,
|
||||
})
|
||||
if request.user.is_authenticated:
|
||||
profile.can_friend = profile.can_friend(request.user)
|
||||
#user.can_follow = user.can_follow(request.user)
|
||||
#user.can_block = user.can_block(request.user)
|
||||
#user.is_blocked = UserBlock.find_block(user, request.user)
|
||||
|
||||
if request.method == 'POST' and request.user.is_authenticated:
|
||||
user = request.user
|
||||
profile = user.profile()
|
||||
@@ -430,9 +435,22 @@ def user_view(request, username):
|
||||
return json_response("Your e-mail address is invalid. Input an e-mail address, or input nothing.")
|
||||
if User.nnid_in_use(request.POST.get('origin_id'), request):
|
||||
return json_response("That Nintendo Network ID is already in use, that would cause confusion.")
|
||||
if user.has_plain_avatar():
|
||||
user.avatar = request.POST.get('avatar') or ''
|
||||
if request.POST.get('avatar') == '1':
|
||||
#if user.has_plain_avatar():
|
||||
# user.avatar = request.POST.get('avatar') or ''
|
||||
# custom handler
|
||||
if request.POST.get('avatar') == '2':
|
||||
if request.FILES.get('screen'):
|
||||
if not request.user.has_freedom():
|
||||
return json_response("Not allowed.")
|
||||
upload = None
|
||||
if request.FILES.get('screen'):
|
||||
# worth noting that the file for the avatar is never cleaned up after the user changes it
|
||||
upload = util.image_upload(request.FILES['screen'], True, avatar=True)
|
||||
if upload == 1:
|
||||
return json_response("sorry, we are racist to the image you uploaded, you have to choose another one")
|
||||
user.avatar = upload
|
||||
user.has_mh = False
|
||||
elif request.POST.get('avatar') == '1':
|
||||
if not request.POST.get('origin_id'):
|
||||
user.has_mh = False
|
||||
profile.origin_id = None
|
||||
@@ -447,13 +465,16 @@ def user_view(request, username):
|
||||
profile.origin_info = None
|
||||
user.avatar = ('s' if getrandbits(1) else '')
|
||||
else:
|
||||
if not request.POST.get('mh'):
|
||||
return json_response('i think you gotta wait for the nnid to retrieve')
|
||||
user.has_mh = True
|
||||
getmii = get_mii(request.POST.get('origin_id'))
|
||||
if not getmii:
|
||||
return json_response('NNID not found')
|
||||
user.avatar = getmii[0]
|
||||
profile.origin_id = getmii[2]
|
||||
profile.origin_info = dumps(getmii)
|
||||
#getmii = get_mii(request.POST.get('origin_id'))
|
||||
#if not getmii:
|
||||
# return json_response('NNID not found')
|
||||
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']])
|
||||
# set the username color
|
||||
if request.POST.get('color'):
|
||||
try:
|
||||
@@ -532,7 +553,7 @@ def user_view(request, username):
|
||||
profile.save()
|
||||
user.save()
|
||||
return HttpResponse()
|
||||
posts = user.get_posts(3, 0, request)
|
||||
posts = user.get_posts(3, 0, request, timezone.now())
|
||||
yeahed = user.get_yeahed(0, 3)
|
||||
for yeah in yeahed:
|
||||
if user.is_me(request):
|
||||
@@ -571,24 +592,30 @@ def user_posts(request, username):
|
||||
title = '{0}\'s posts'.format(user.nickname)
|
||||
profile = user.profile()
|
||||
profile.setup(request)
|
||||
if hasattr(profile, 'is_blocked'):
|
||||
return render(request, 'closedverse_main/user_blocked.html', {
|
||||
'classes': ['profile-top'],
|
||||
'user': user,
|
||||
'profile': profile,
|
||||
})
|
||||
|
||||
if request.GET.get('offset'):
|
||||
posts = user.get_posts(50, int(request.GET['offset']), request)
|
||||
else:
|
||||
posts = user.get_posts(50, 0, request)
|
||||
if posts.count() > 49:
|
||||
if request.GET.get('offset'):
|
||||
next_offset = int(request.GET['offset']) + 50
|
||||
else:
|
||||
next_offset = 50
|
||||
offset = int(request.GET.get('offset', 0))
|
||||
if request.GET.get('offset_time'):
|
||||
offset_time = datetime.fromisoformat(request.GET['offset_time'])
|
||||
else:
|
||||
offset_time = timezone.now()
|
||||
|
||||
posts = user.get_posts(50, offset, request, offset_time)
|
||||
next_offset = None
|
||||
if posts.count() > 49:
|
||||
next_offset = offset + 50
|
||||
|
||||
if request.META.get('HTTP_X_AUTOPAGERIZE'):
|
||||
return render(request, 'closedverse_main/elements/u-post-list.html', {
|
||||
return (debug(request, username) if 'HTTP_DIS' in request.META else render(request, 'closedverse_main/elements/u-post-list.html', {
|
||||
'posts': posts,
|
||||
'next': next_offset,
|
||||
})
|
||||
'time': offset_time.isoformat(),
|
||||
}))
|
||||
else:
|
||||
return render(request, 'closedverse_main/user_posts.html', {
|
||||
'user': user,
|
||||
@@ -596,6 +623,7 @@ def user_posts(request, username):
|
||||
'posts': posts,
|
||||
'profile': profile,
|
||||
'next': next_offset,
|
||||
'time': offset_time.isoformat(),
|
||||
# Copied from the above, if you change the last ogdata occurrence then change this one
|
||||
'ogdata': {
|
||||
'title': title,
|
||||
@@ -616,6 +644,12 @@ def user_yeahs(request, username):
|
||||
title = '{0}\'s yeahs'.format(user.nickname)
|
||||
profile = user.profile()
|
||||
profile.setup(request)
|
||||
if hasattr(profile, 'is_blocked'):
|
||||
return render(request, 'closedverse_main/user_blocked.html', {
|
||||
'classes': ['profile-top'],
|
||||
'user': user,
|
||||
'profile': profile,
|
||||
})
|
||||
|
||||
if not profile.yeahs_visible:
|
||||
raise Http404()
|
||||
@@ -667,25 +701,31 @@ def user_comments(request, username):
|
||||
title = '{0}\'s comments'.format(user.nickname)
|
||||
profile = user.profile()
|
||||
profile.setup(request)
|
||||
if hasattr(profile, 'is_blocked'):
|
||||
return render(request, 'closedverse_main/user_blocked.html', {
|
||||
'classes': ['profile-top'],
|
||||
'user': user,
|
||||
'profile': profile,
|
||||
})
|
||||
|
||||
if not profile.comments_visible:
|
||||
raise Http404()
|
||||
|
||||
if request.GET.get('offset'):
|
||||
posts = user.get_comments(50, int(request.GET['offset']), request)
|
||||
else:
|
||||
posts = user.get_comments(50, 0, request)
|
||||
if posts.count() > 19:
|
||||
if request.GET.get('offset'):
|
||||
next_offset = int(request.GET['offset']) + 20
|
||||
else:
|
||||
next_offset = 20
|
||||
offset = int(request.GET.get('offset', 0))
|
||||
if request.GET.get('offset_time'):
|
||||
offset_time = datetime.fromisoformat(request.GET['offset_time'])
|
||||
else:
|
||||
offset_time = timezone.now()
|
||||
posts = user.get_comments(20, offset, request, offset_time)
|
||||
next_offset = None
|
||||
if posts.count() > 19:
|
||||
next_offset = offset + 20
|
||||
|
||||
if request.META.get('HTTP_X_AUTOPAGERIZE'):
|
||||
return render(request, 'closedverse_main/elements/u-post-list.html', {
|
||||
'posts': posts,
|
||||
'next': next_offset,
|
||||
'time': offset_time.isoformat(),
|
||||
})
|
||||
else:
|
||||
return render(request, 'closedverse_main/user_comments.html', {
|
||||
@@ -694,6 +734,7 @@ def user_comments(request, username):
|
||||
'posts': posts,
|
||||
'profile': profile,
|
||||
'next': next_offset,
|
||||
'time': offset_time.isoformat(),
|
||||
})
|
||||
def user_following(request, username):
|
||||
"""User following page"""
|
||||
@@ -706,6 +747,12 @@ def user_following(request, username):
|
||||
title = '{0}\'s follows'.format(user.nickname)
|
||||
profile = user.profile()
|
||||
profile.setup(request)
|
||||
if hasattr(profile, 'is_blocked'):
|
||||
return render(request, 'closedverse_main/user_blocked.html', {
|
||||
'classes': ['profile-top'],
|
||||
'user': user,
|
||||
'profile': profile,
|
||||
})
|
||||
|
||||
if request.GET.get('offset'):
|
||||
following_list = user.get_following(20, int(request.GET['offset']))
|
||||
@@ -748,6 +795,12 @@ def user_followers(request, username):
|
||||
title = '{0}\'s followers'.format(user.nickname)
|
||||
profile = user.profile()
|
||||
profile.setup(request)
|
||||
if hasattr(profile, 'is_blocked'):
|
||||
return render(request, 'closedverse_main/user_blocked.html', {
|
||||
'classes': ['profile-top'],
|
||||
'user': user,
|
||||
'profile': profile,
|
||||
})
|
||||
|
||||
if request.GET.get('offset'):
|
||||
followers_list = user.get_followers(20, int(request.GET['offset']))
|
||||
@@ -790,6 +843,12 @@ def user_friends(request, username):
|
||||
title = '{0}\'s friends'.format(user.nickname)
|
||||
profile = user.profile()
|
||||
profile.setup(request)
|
||||
if hasattr(profile, 'is_blocked'):
|
||||
return render(request, 'closedverse_main/user_blocked.html', {
|
||||
'classes': ['profile-top'],
|
||||
'user': user,
|
||||
'profile': profile,
|
||||
})
|
||||
|
||||
if request.GET.get('offset'):
|
||||
friends_list = Friendship.get_friendships(user, 20, int(request.GET['offset']))
|
||||
@@ -853,21 +912,21 @@ def community_view(request, community):
|
||||
return HttpResponseForbidden()
|
||||
if not request.user.is_authenticated and communities.require_auth:
|
||||
return render(request, 'com_locked.html')
|
||||
if request.GET.get('offset'):
|
||||
posts = communities.get_posts(50, int(request.GET['offset']), request)
|
||||
else:
|
||||
posts = communities.get_posts(50, 0, request)
|
||||
if posts.count() > 49:
|
||||
if request.GET.get('offset'):
|
||||
next_offset = int(request.GET['offset']) + 50
|
||||
else:
|
||||
next_offset = 50
|
||||
offset = int(request.GET.get('offset', 0))
|
||||
if request.GET.get('offset_time'):
|
||||
offset_time = datetime.fromisoformat(request.GET['offset_time'])
|
||||
else:
|
||||
offset_time = timezone.now()
|
||||
|
||||
posts = communities.get_posts(50, offset, request, offset_time)
|
||||
next_offset = None
|
||||
if posts.count() > 49:
|
||||
next_offset = offset + 50
|
||||
if request.META.get('HTTP_X_AUTOPAGERIZE'):
|
||||
return render(request, 'closedverse_main/elements/post-list.html', {
|
||||
'posts': posts,
|
||||
'next': next_offset,
|
||||
'time': offset_time.isoformat(),
|
||||
})
|
||||
else:
|
||||
return render(request, 'closedverse_main/community_view.html', {
|
||||
@@ -876,6 +935,7 @@ def community_view(request, community):
|
||||
'community': communities,
|
||||
'posts': posts,
|
||||
'next': next_offset,
|
||||
'time': offset_time.isoformat(),
|
||||
'ogdata': {
|
||||
'title': communities.name,
|
||||
'description': communities.description,
|
||||
@@ -1009,7 +1069,7 @@ def community_create_action(request):
|
||||
return json_response('Done.')
|
||||
@login_required
|
||||
def post_create(request, community):
|
||||
if request.method == 'POST' and request.is_ajax():
|
||||
if request.method == 'POST':
|
||||
# Wake
|
||||
request.user.wake(request.META['HTTP_CF_CONNECTING_IP'])
|
||||
# Required
|
||||
@@ -1031,11 +1091,13 @@ def post_create(request, community):
|
||||
return json_response({
|
||||
1: "Your post is too long ("+str(len(request.POST['body']))+" characters, 2200 max).",
|
||||
2: "The image you've uploaded is invalid.",
|
||||
3: "You're making posts too fast, wait a few seconds and try again.",
|
||||
3: "You're posting too quickly, wait a few seconds and try again.",
|
||||
4: "Apparently, you're not allowed to post here.",
|
||||
5: "Uh-oh, that URL wasn't valid..",
|
||||
6: "Not allowed.",
|
||||
7: "Please don't spam.",
|
||||
9: "You're very funny. Unfortunately your funniness blah blah blah fuck off.",
|
||||
10: "No mr white, you can't make a post entirely consistant of spaces",
|
||||
}.get(new_post))
|
||||
# Render correctly whether we're posting to Activity Feed
|
||||
if community.is_activity():
|
||||
@@ -1243,13 +1305,15 @@ def poll_unvote(request, poll):
|
||||
@login_required
|
||||
def user_follow(request, username):
|
||||
user = get_object_or_404(User, username=username)
|
||||
if settings.PROD:
|
||||
"""
|
||||
if settings.CLOSEDVERSE_PROD:
|
||||
# Issue 69420: PF2M is getting more follows than me.
|
||||
if user.username == 'PF2M':
|
||||
try:
|
||||
User.objects.get(id=1).follow(request.user)
|
||||
except:
|
||||
pass
|
||||
"""
|
||||
if user.follow(request.user):
|
||||
# Give the notification!
|
||||
Notification.give_notification(request.user, 4, user)
|
||||
@@ -1679,12 +1743,12 @@ 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()
|
||||
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:
|
||||
@@ -1764,7 +1828,7 @@ def create_invite(request):
|
||||
# Disabling login requirement since it's in signup now. Regret?
|
||||
#@login_required
|
||||
def origin_id(request):
|
||||
if not request.is_ajax():
|
||||
if not request.headers.get('x-requested-with') == 'XMLHttpRequest':
|
||||
return HttpResponse("<a href='https://github.com/ariankordi/closedverse/blob/master/closedverse_main/util.py#L44-L86'>Please do not use this as an API!</a>")
|
||||
if not request.POST.get('a'):
|
||||
return HttpResponseBadRequest()
|
||||
@@ -1791,7 +1855,6 @@ def help_complaint(request):
|
||||
return json_response('Please do not send complaints that quickly (very very sorry, but there\'s a 5 minute wait to prevent spam)')
|
||||
save = request.user.complaint_set.create(type=int(request.POST['a']), body=request.POST['b'], sex=request.POST.get('c', 2))
|
||||
return HttpResponse()
|
||||
@login_required
|
||||
def server_stat(request):
|
||||
all_stats = {
|
||||
'communities': Community.objects.filter().count(),
|
||||
@@ -1874,10 +1937,6 @@ def change_password_set(request):
|
||||
def whatads(request):
|
||||
return render(request, 'closedverse_main/help/whatads.html', {'title': 'What are user-generated ads?'})
|
||||
@login_required
|
||||
def active_clones(request):
|
||||
return render(request, 'closedverse_main/help/Active_clones.html', {'title': 'Active Clones'})
|
||||
def help_approval(request):
|
||||
return render(request, 'closedverse_main/help/help_approval.html', {'title': 'Approval system'})
|
||||
def help_rules(request):
|
||||
return render(request, 'closedverse_main/help/rules.html', {'title': 'Cedar Three Rules', 'age': settings.age_allowed})
|
||||
def help_faq(request):
|
||||
|
||||
Reference in New Issue
Block a user