fix detail page 502 step 2: calculate relationship by local cached data
This commit is contained in:
parent
879c21ca05
commit
8d8c69343c
3 changed files with 46 additions and 66 deletions
|
@ -159,63 +159,27 @@ class UserOwnedEntity(models.Model):
|
|||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def is_visible_to(self, viewer):
|
||||
owner = self.owner
|
||||
if owner == viewer:
|
||||
return True
|
||||
if viewer.is_blocking(owner) or owner.is_blocking(viewer) or viewer.is_muting(owner):
|
||||
return False
|
||||
if self.is_private:
|
||||
return viewer.is_following(owner)
|
||||
else:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def get_available(cls, entity, request_user, token):
|
||||
# TODO add amount limit for once query
|
||||
"""
|
||||
Returns all avaliable user-owned entities related to given entity.
|
||||
This method handles mute/block relationships and private/public visibilities.
|
||||
"""
|
||||
# the foreign key field that points to entity
|
||||
# has to be named as the lower case name of that entity
|
||||
# e.g. SongMark.get_available(song, request.user, request.session['oauth_token'])
|
||||
query_kwargs = {entity.__class__.__name__.lower(): entity}
|
||||
user_owned_entities = cls.objects.filter(
|
||||
**query_kwargs).order_by("-edited_time")
|
||||
|
||||
# every user should only be abled to have one user owned entity for each entity
|
||||
# this is guaranteed by models
|
||||
id_list = []
|
||||
|
||||
# none_index tracks those failed cross site id query
|
||||
none_index = []
|
||||
|
||||
for (i, entity) in enumerate(user_owned_entities):
|
||||
if entity.owner.mastodon_site == request_user.mastodon_site:
|
||||
id_list.append(entity.owner.mastodon_id)
|
||||
else:
|
||||
# TODO there could be many requests therefore make the pulling asynchronized
|
||||
cross_site_id = get_cross_site_id(
|
||||
entity.owner, request_user.mastodon_site, token)
|
||||
if not cross_site_id is None:
|
||||
id_list.append(cross_site_id)
|
||||
else:
|
||||
none_index.append(i)
|
||||
# populate those query-failed None postions
|
||||
# to ensure the consistency of the orders of
|
||||
# the three(id_list, user_owned_entities, relationships)
|
||||
id_list.append(request_user.mastodon_id)
|
||||
|
||||
# Mastodon request
|
||||
relationships = get_relationships(
|
||||
request_user.mastodon_site, id_list, token)
|
||||
mute_block_blocked_index = []
|
||||
following_index = []
|
||||
for i, r in enumerate(relationships):
|
||||
# the order of relationships is corresponding to the id_list,
|
||||
# and the order of id_list is the same as user_owned_entiies
|
||||
if r['blocking'] or r['blocked_by'] or r['muting']:
|
||||
mute_block_blocked_index.append(i)
|
||||
if r['following']:
|
||||
following_index.append(i)
|
||||
available_entities = [
|
||||
e for i, e in enumerate(user_owned_entities)
|
||||
if ((e.is_private == True and i in following_index) or e.is_private == False or e.owner == request_user)
|
||||
and not i in mute_block_blocked_index and not i in none_index
|
||||
]
|
||||
return available_entities
|
||||
all_entities = cls.objects.filter(**query_kwargs).order_by("-edited_time") # get all marks for song
|
||||
visible_entities = list(filter(lambda _entity: _entity.is_visible_to(request_user), all_entities))
|
||||
return visible_entities
|
||||
|
||||
@classmethod
|
||||
def get_available_by_user(cls, owner, is_following):
|
||||
def get_available_by_user(cls, owner, is_following): # FIXME
|
||||
"""
|
||||
Returns all avaliable owner's entities.
|
||||
Mute/Block relation is not handled in this method.
|
||||
|
|
|
@ -136,15 +136,10 @@ def get_site_id(username, user_site, target_site, token):
|
|||
|
||||
# high level api below
|
||||
def get_relationship(request_user, target_user, token):
|
||||
if request_user.mastodon_site == target_user.mastodon_site:
|
||||
return get_relationships(request_user.mastodon_site, target_user.mastodon_id, token)
|
||||
else:
|
||||
cross_site_id = get_cross_site_id(target_user, request_user.mastodon_site, token)
|
||||
if cross_site_id is None:
|
||||
return [{'blocked_by': True}] # boldly assume blocked(?!) if no relationship found
|
||||
# FIXME should check the reverse direction? but need either cache the target user's oauth token or her blocked list
|
||||
else:
|
||||
return get_relationships(request_user.mastodon_site, cross_site_id, token)
|
||||
return [{
|
||||
'blocked_by': target_user.is_blocking(request_user),
|
||||
'following': request_user.is_following(target_user),
|
||||
}]
|
||||
|
||||
|
||||
def get_cross_site_id(target_user, target_site, token):
|
||||
|
|
|
@ -31,6 +31,7 @@ class User(AbstractUser):
|
|||
mastodon_following = models.JSONField(default=list)
|
||||
mastodon_mutes = models.JSONField(default=list)
|
||||
mastodon_blocks = models.JSONField(default=list)
|
||||
mastodon_domain_blocks = models.JSONField(default=list)
|
||||
mastodon_account = models.JSONField(default=dict)
|
||||
mastodon_last_refresh = models.DateTimeField(default=timezone.now)
|
||||
# store the latest read announcement id,
|
||||
|
@ -43,13 +44,17 @@ class User(AbstractUser):
|
|||
fields=['username', 'mastodon_site'], name="unique_user_identity")
|
||||
]
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
""" Automatically populate password field with settings.DEFAULT_PASSWORD before saving."""
|
||||
self.set_password(settings.DEFAULT_PASSWORD)
|
||||
return super().save(*args, **kwargs)
|
||||
# def save(self, *args, **kwargs):
|
||||
# """ Automatically populate password field with settings.DEFAULT_PASSWORD before saving."""
|
||||
# self.set_password(settings.DEFAULT_PASSWORD)
|
||||
# return super().save(*args, **kwargs)
|
||||
|
||||
@property
|
||||
def mastodon_username(self):
|
||||
return self.username + '@' + self.mastodon_site
|
||||
|
||||
def __str__(self):
|
||||
return self.username + '@' + self.mastodon_site
|
||||
return self.mastodon_username
|
||||
|
||||
def refresh_mastodon_data(self):
|
||||
""" Try refresh account data from mastodon server, return true if refreshed successfully, note it will not save to db """
|
||||
|
@ -65,11 +70,27 @@ class User(AbstractUser):
|
|||
self.mastodon_following = get_related_acct_list(self.mastodon_site, self.mastodon_token, f'/api/v1/accounts/{self.mastodon_id}/following')
|
||||
self.mastodon_mutes = get_related_acct_list(self.mastodon_site, self.mastodon_token, '/api/v1/mutes')
|
||||
self.mastodon_blocks = get_related_acct_list(self.mastodon_site, self.mastodon_token, '/api/v1/blocks')
|
||||
self.mastodon_domain_blocks = get_related_acct_list(self.mastodon_site, self.mastodon_token, '/api/v1/domain_blocks')
|
||||
updated = True
|
||||
elif code == 401:
|
||||
self.mastodon_token = ''
|
||||
return updated
|
||||
|
||||
def is_blocking(self, target):
|
||||
return target.mastodon_username in self.mastodon_blocks or target.mastodon_site in self.mastodon_domain_blocks
|
||||
|
||||
def is_blocked_by(self, target):
|
||||
return target.is_blocking(self)
|
||||
|
||||
def is_muting(self, target):
|
||||
return target.mastodon_username in self.mastodon_mutes
|
||||
|
||||
def is_following(self, target):
|
||||
return self.mastodon_username in target.mastodon_followers if target.mastodon_locked else self.mastodon_username in target.mastodon_followers or target.mastodon_username in self.mastodon_following
|
||||
|
||||
def is_followed_by(self, target):
|
||||
return target.is_following(self)
|
||||
|
||||
|
||||
class Preference(models.Model):
|
||||
user = models.OneToOneField(User, models.CASCADE, primary_key=True)
|
||||
|
|
Loading…
Add table
Reference in a new issue