avoid use of depreciated datetime.utcnow

This commit is contained in:
rimu 2023-12-12 08:53:35 +13:00
parent 606024494d
commit 5b6c9f39b2
11 changed files with 80 additions and 72 deletions

View file

@ -10,7 +10,7 @@ from app.post.routes import continue_discussion, show_post
from app.user.routes import show_profile from app.user.routes import show_profile
from app.constants import POST_TYPE_LINK, POST_TYPE_IMAGE, SUBSCRIPTION_MEMBER from app.constants import POST_TYPE_LINK, POST_TYPE_IMAGE, SUBSCRIPTION_MEMBER
from app.models import User, Community, CommunityJoinRequest, CommunityMember, CommunityBan, ActivityPubLog, Post, \ from app.models import User, Community, CommunityJoinRequest, CommunityMember, CommunityBan, ActivityPubLog, Post, \
PostReply, Instance, PostVote, PostReplyVote, File, AllowedInstances, BannedInstances PostReply, Instance, PostVote, PostReplyVote, File, AllowedInstances, BannedInstances, utcnow
from app.activitypub.util import public_key, users_total, active_half_year, active_month, local_posts, local_comments, \ from app.activitypub.util import public_key, users_total, active_half_year, active_month, local_posts, local_comments, \
post_to_activity, find_actor_or_create, default_context, instance_blocked, find_reply_parent, find_liked_object, \ post_to_activity, find_actor_or_create, default_context, instance_blocked, find_reply_parent, find_liked_object, \
lemmy_site_data, instance_weight, is_activitypub_request lemmy_site_data, instance_weight, is_activitypub_request
@ -125,9 +125,9 @@ def lemmy_federated_instances():
instance_data['version'] = instance.version instance_data['version'] = instance.version
linked.append(instance_data) linked.append(instance_data)
for instance in AllowedInstances.query.all(): for instance in AllowedInstances.query.all():
allowed.append({"id": instance.id, "domain": instance.domain, "published": datetime.utcnow(), "updated": datetime.utcnow()}) allowed.append({"id": instance.id, "domain": instance.domain, "published": utcnow(), "updated": utcnow()})
for instance in BannedInstances.query.all(): for instance in BannedInstances.query.all():
blocked.append({"id": instance.id, "domain": instance.domain, "published": datetime.utcnow(), "updated": datetime.utcnow()}) blocked.append({"id": instance.id, "domain": instance.domain, "published": utcnow(), "updated": utcnow()})
return jsonify({ return jsonify({
"federated_instances": { "federated_instances": {
"linked": linked, "linked": linked,
@ -290,7 +290,7 @@ def shared_inbox():
community = find_actor_or_create(community_ap_id) community = find_actor_or_create(community_ap_id)
user = find_actor_or_create(user_ap_id) user = find_actor_or_create(user_ap_id)
if user and community: if user and community:
user.last_seen = community.last_active = datetime.utcnow() user.last_seen = community.last_active = utcnow()
object_type = request_json['object']['type'] object_type = request_json['object']['type']
new_content_types = ['Page', 'Article', 'Link', 'Note'] new_content_types = ['Page', 'Article', 'Link', 'Note']
@ -348,7 +348,7 @@ def shared_inbox():
if post is not None: if post is not None:
db.session.add(post) db.session.add(post)
community.post_count += 1 community.post_count += 1
community.last_active = datetime.utcnow() community.last_active = utcnow()
activity_log.result = 'success' activity_log.result = 'success'
db.session.commit() db.session.commit()
vote = PostVote(user_id=user.id, author_id=post.user_id, vote = PostVote(user_id=user.id, author_id=post.user_id,
@ -382,7 +382,7 @@ def shared_inbox():
db.session.add(post_reply) db.session.add(post_reply)
post.reply_count += 1 post.reply_count += 1
community.post_reply_count += 1 community.post_reply_count += 1
community.last_active = post.last_active = datetime.utcnow() community.last_active = post.last_active = utcnow()
activity_log.result = 'success' activity_log.result = 'success'
db.session.commit() db.session.commit()
vote = PostReplyVote(user_id=user.id, author_id=post_reply.user_id, post_reply_id=post_reply.id, vote = PostReplyVote(user_id=user.id, author_id=post_reply.user_id, post_reply_id=post_reply.id,
@ -400,7 +400,7 @@ def shared_inbox():
community = find_actor_or_create(community_ap_id) community = find_actor_or_create(community_ap_id)
user = find_actor_or_create(user_ap_id) user = find_actor_or_create(user_ap_id)
if user and community: if user and community:
user.last_seen = community.last_active = datetime.utcnow() user.last_seen = community.last_active = utcnow()
object_type = request_json['object']['object']['type'] object_type = request_json['object']['object']['type']
new_content_types = ['Page', 'Article', 'Link', 'Note'] new_content_types = ['Page', 'Article', 'Link', 'Note']
if object_type in new_content_types: # create a new post if object_type in new_content_types: # create a new post
@ -531,7 +531,7 @@ def shared_inbox():
banned = CommunityBan.query.filter_by(user_id=user.id, banned = CommunityBan.query.filter_by(user_id=user.id,
community_id=community.id).first() community_id=community.id).first()
if banned is None: if banned is None:
user.last_seen = datetime.utcnow() user.last_seen = utcnow()
if community_membership(user, community) != SUBSCRIPTION_MEMBER: if community_membership(user, community) != SUBSCRIPTION_MEMBER:
member = CommunityMember(user_id=user.id, community_id=community.id) member = CommunityMember(user_id=user.id, community_id=community.id)
db.session.add(member) db.session.add(member)
@ -592,7 +592,7 @@ def shared_inbox():
user = find_actor_or_create(user_ap_id) user = find_actor_or_create(user_ap_id)
community = find_actor_or_create(community_ap_id) community = find_actor_or_create(community_ap_id)
if user and community: if user and community:
user.last_seen = datetime.utcnow() user.last_seen = utcnow()
member = CommunityMember.query.filter_by(user_id=user.id, community_id=community.id).first() member = CommunityMember.query.filter_by(user_id=user.id, community_id=community.id).first()
join_request = CommunityJoinRequest.query.filter_by(user_id=user.id, join_request = CommunityJoinRequest.query.filter_by(user_id=user.id,
community_id=community.id).first() community_id=community.id).first()
@ -614,7 +614,7 @@ def shared_inbox():
if '/post/' in target_ap_id: if '/post/' in target_ap_id:
post = Post.query.filter_by(ap_id=target_ap_id).first() post = Post.query.filter_by(ap_id=target_ap_id).first()
if user and post: if user and post:
user.last_seen = datetime.utcnow() user.last_seen = utcnow()
existing_vote = PostVote.query.filter_by(user_id=user.id, post_id=post.id).first() existing_vote = PostVote.query.filter_by(user_id=user.id, post_id=post.id).first()
if existing_vote: if existing_vote:
post.author.reputation -= existing_vote.effect post.author.reputation -= existing_vote.effect
@ -677,7 +677,7 @@ def shared_inbox():
elif 'content' in request_json['object']: elif 'content' in request_json['object']:
post.body_html = allowlist_html(request_json['object']['content']) post.body_html = allowlist_html(request_json['object']['content'])
post.body = html_to_markdown(post.body_html) post.body = html_to_markdown(post.body_html)
post.edited_at = datetime.utcnow() post.edited_at = utcnow()
db.session.commit() db.session.commit()
activity_log.result = 'success' activity_log.result = 'success'
elif request_json['object']['type'] == 'Note': # Editing a reply elif request_json['object']['type'] == 'Note': # Editing a reply
@ -690,7 +690,7 @@ def shared_inbox():
elif 'content' in request_json['object']: elif 'content' in request_json['object']:
reply.body_html = allowlist_html(request_json['object']['content']) reply.body_html = allowlist_html(request_json['object']['content'])
reply.body = html_to_markdown(reply.body_html) reply.body = html_to_markdown(reply.body_html)
reply.edited_at = datetime.utcnow() reply.edited_at = utcnow()
db.session.commit() db.session.commit()
activity_log.result = 'success' activity_log.result = 'success'
elif request_json['type'] == 'Delete': elif request_json['type'] == 'Delete':
@ -722,7 +722,7 @@ def shared_inbox():
if '/post/' in target_ap_id: if '/post/' in target_ap_id:
post = Post.query.filter_by(ap_id=target_ap_id).first() post = Post.query.filter_by(ap_id=target_ap_id).first()
if user and post: if user and post:
user.last_seen = datetime.utcnow() user.last_seen = utcnow()
existing_vote = PostVote.query.filter_by(user_id=user.id, post_id=post.id).first() existing_vote = PostVote.query.filter_by(user_id=user.id, post_id=post.id).first()
if not existing_vote: if not existing_vote:
post.up_votes += 1 post.up_votes += 1
@ -748,7 +748,7 @@ def shared_inbox():
db.session.add(vote) db.session.add(vote)
activity_log.result = 'success' activity_log.result = 'success'
elif user and comment: elif user and comment:
user.last_seen = datetime.utcnow() user.last_seen = utcnow()
existing_vote = PostReplyVote.query.filter_by(user_id=user.id, existing_vote = PostReplyVote.query.filter_by(user_id=user.id,
post_reply_id=comment.id).first() post_reply_id=comment.id).first()
if not existing_vote: if not existing_vote:
@ -792,7 +792,7 @@ def shared_inbox():
if '/post/' in target_ap_id: if '/post/' in target_ap_id:
post = Post.query.filter_by(ap_id=target_ap_id).first() post = Post.query.filter_by(ap_id=target_ap_id).first()
if user and comment: if user and comment:
user.last_seen = datetime.utcnow() user.last_seen = utcnow()
existing_vote = PostReplyVote.query.filter_by(user_id=user.id, existing_vote = PostReplyVote.query.filter_by(user_id=user.id,
post_reply_id=comment.id).first() post_reply_id=comment.id).first()
if not existing_vote: if not existing_vote:
@ -823,7 +823,7 @@ def shared_inbox():
pass # they have already downvoted this reply pass # they have already downvoted this reply
activity_log.result = 'success' activity_log.result = 'success'
elif user and post: elif user and post:
user.last_seen = datetime.utcnow() user.last_seen = utcnow()
existing_vote = PostVote.query.filter_by(user_id=user.id, post_id=post.id).first() existing_vote = PostVote.query.filter_by(user_id=user.id, post_id=post.id).first()
if not existing_vote: if not existing_vote:
effect = -1.0 effect = -1.0

View file

@ -46,6 +46,7 @@ from pyld import jsonld
from app.activitypub.util import default_context from app.activitypub.util import default_context
from app.constants import DATETIME_MS_FORMAT from app.constants import DATETIME_MS_FORMAT
from app.models import utcnow
def http_date(epoch_seconds=None): def http_date(epoch_seconds=None):
@ -392,7 +393,7 @@ class LDSignature:
options: dict[str, str] = { options: dict[str, str] = {
"@context": "https://w3id.org/identity/v1", "@context": "https://w3id.org/identity/v1",
"creator": key_id, "creator": key_id,
"created": format_ld_date(datetime.utcnow()), "created": format_ld_date(utcnow()),
} }
# Get the normalised hash of each document # Get the normalised hash of each document
final_hash = cls.normalized_hash(options) + cls.normalized_hash(document) final_hash = cls.normalized_hash(options) + cls.normalized_hash(document)

View file

@ -5,7 +5,7 @@ from typing import Union, Tuple
from flask import current_app, request from flask import current_app, request
from sqlalchemy import text from sqlalchemy import text
from app import db, cache from app import db, cache
from app.models import User, Post, Community, BannedInstances, File, PostReply, AllowedInstances, Instance from app.models import User, Post, Community, BannedInstances, File, PostReply, AllowedInstances, Instance, utcnow
import time import time
import base64 import base64
import requests import requests
@ -246,7 +246,7 @@ def find_actor_or_create(actor: str) -> Union[User, Community, None]:
ap_inbox_url=activity_json['endpoints']['sharedInbox'], ap_inbox_url=activity_json['endpoints']['sharedInbox'],
ap_followers_url=activity_json['followers'] if 'followers' in activity_json else None, ap_followers_url=activity_json['followers'] if 'followers' in activity_json else None,
ap_preferred_username=activity_json['preferredUsername'], ap_preferred_username=activity_json['preferredUsername'],
ap_fetched_at=datetime.utcnow(), ap_fetched_at=utcnow(),
ap_domain=server, ap_domain=server,
public_key=activity_json['publicKey']['publicKeyPem'], public_key=activity_json['publicKey']['publicKeyPem'],
# language=community_json['language'][0]['identifier'] # todo: language # language=community_json['language'][0]['identifier'] # todo: language
@ -277,7 +277,7 @@ def find_actor_or_create(actor: str) -> Union[User, Community, None]:
ap_profile_id=activity_json['id'], ap_profile_id=activity_json['id'],
ap_followers_url=activity_json['followers'], ap_followers_url=activity_json['followers'],
ap_inbox_url=activity_json['endpoints']['sharedInbox'], ap_inbox_url=activity_json['endpoints']['sharedInbox'],
ap_fetched_at=datetime.utcnow(), ap_fetched_at=utcnow(),
ap_domain=server, ap_domain=server,
public_key=activity_json['publicKey']['publicKeyPem'], public_key=activity_json['publicKey']['publicKeyPem'],
# language=community_json['language'][0]['identifier'] # todo: language # language=community_json['language'][0]['identifier'] # todo: language

View file

@ -49,7 +49,7 @@ def admin_home():
@permission_required('change instance settings') @permission_required('change instance settings')
def admin_activities(): def admin_activities():
db.session.query(ActivityPubLog).filter( db.session.query(ActivityPubLog).filter(
ActivityPubLog.created_at < datetime.utcnow() - timedelta(days=3)).delete() ActivityPubLog.created_at < aware_utcnow() - timedelta(days=3)).delete()
db.session.commit() db.session.commit()
return render_template('admin/activities.html', title=_('ActivityPub Log'), return render_template('admin/activities.html', title=_('ActivityPub Log'),

View file

@ -7,7 +7,7 @@ from app import db
from app.auth import bp from app.auth import bp
from app.auth.forms import LoginForm, RegistrationForm, ResetPasswordRequestForm, ResetPasswordForm from app.auth.forms import LoginForm, RegistrationForm, ResetPasswordRequestForm, ResetPasswordForm
from app.auth.util import random_token from app.auth.util import random_token
from app.models import User from app.models import User, utcnow
from app.auth.email import send_password_reset_email, send_welcome_email, send_verification_email from app.auth.email import send_password_reset_email, send_welcome_email, send_verification_email
from app.activitypub.signature import RsaKeys from app.activitypub.signature import RsaKeys
from app.utils import render_template from app.utils import render_template
@ -41,7 +41,7 @@ def login():
flash(_('Invalid password')) flash(_('Invalid password'))
return redirect(url_for('auth.login')) return redirect(url_for('auth.login'))
login_user(user, remember=True) login_user(user, remember=True)
current_user.last_seen = datetime.utcnow() current_user.last_seen = utcnow()
current_user.verification_token = '' current_user.verification_token = ''
db.session.commit() db.session.commit()
next_page = request.args.get('next') next_page = request.args.get('next')
@ -143,7 +143,7 @@ def verify_email(token):
if user.verified: # guard against users double-clicking the link in the email if user.verified: # guard against users double-clicking the link in the email
return redirect(url_for('main.index')) return redirect(url_for('main.index'))
user.verified = True user.verified = True
user.last_seen = datetime.utcnow() user.last_seen = utcnow()
private_key, public_key = RsaKeys.generate_keypair() private_key, public_key = RsaKeys.generate_keypair()
user.private_key = private_key user.private_key = private_key
user.public_key = public_key user.public_key = public_key

View file

@ -10,7 +10,8 @@ import os
from app.auth.email import send_verification_email from app.auth.email import send_verification_email
from app.auth.util import random_token from app.auth.util import random_token
from app.models import Settings, BannedInstances, Interest, Role, User, RolePermission, Domain, ActivityPubLog from app.models import Settings, BannedInstances, Interest, Role, User, RolePermission, Domain, ActivityPubLog, \
utcnow
from app.utils import file_get_contents, retrieve_block_list from app.utils import file_get_contents, retrieve_block_list
@ -125,7 +126,7 @@ def register(app):
with app.app_context(): with app.app_context():
"""Remove activity older than 3 days""" """Remove activity older than 3 days"""
db.session.query(ActivityPubLog).filter( db.session.query(ActivityPubLog).filter(
ActivityPubLog.created_at < datetime.utcnow() - timedelta(days=3)).delete() ActivityPubLog.created_at < utcnow() - timedelta(days=3)).delete()
db.session.commit() db.session.commit()

View file

@ -13,7 +13,7 @@ from app.community.util import search_for_community, community_url_exists, actor
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, POST_TYPE_LINK, POST_TYPE_ARTICLE, POST_TYPE_IMAGE, \ from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, POST_TYPE_LINK, POST_TYPE_ARTICLE, POST_TYPE_IMAGE, \
SUBSCRIPTION_PENDING SUBSCRIPTION_PENDING
from app.models import User, Community, CommunityMember, CommunityJoinRequest, CommunityBan, Post, \ from app.models import User, Community, CommunityMember, CommunityJoinRequest, CommunityBan, Post, \
File, PostVote File, PostVote, utcnow
from app.community import bp from app.community import bp
from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \ from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \
shorten_string, markdown_to_text, domain_from_url, validate_image, gibberish, community_membership, ap_datetime, \ shorten_string, markdown_to_text, domain_from_url, validate_image, gibberish, community_membership, ap_datetime, \
@ -259,7 +259,7 @@ def add_post(actor):
post = Post(user_id=current_user.id, community_id=form.communities.data) post = Post(user_id=current_user.id, community_id=form.communities.data)
save_post(form, post) save_post(form, post)
community.post_count += 1 community.post_count += 1
community.last_active = datetime.utcnow() community.last_active = utcnow()
db.session.commit() db.session.commit()
post.ap_id = f"https://{current_app.config['SERVER_NAME']}/post/{post.id}" post.ap_id = f"https://{current_app.config['SERVER_NAME']}/post/{post.id}"
db.session.commit() db.session.commit()
@ -285,7 +285,7 @@ def add_post(actor):
'commentsEnabled': post.comments_enabled, 'commentsEnabled': post.comments_enabled,
'sensitive': post.nsfw, 'sensitive': post.nsfw,
'nsfl': post.nsfl, 'nsfl': post.nsfl,
'published': ap_datetime(datetime.utcnow()), 'published': ap_datetime(utcnow()),
'audience': community.ap_profile_id 'audience': community.ap_profile_id
} }
create = { create = {

View file

@ -9,7 +9,7 @@ from pillow_heif import register_heif_opener
from app import db, cache from app import db, cache
from app.constants import POST_TYPE_ARTICLE, POST_TYPE_LINK, POST_TYPE_IMAGE from app.constants import POST_TYPE_ARTICLE, POST_TYPE_LINK, POST_TYPE_IMAGE
from app.models import Community, File, BannedInstances, PostReply, PostVote, Post from app.models import Community, File, BannedInstances, PostReply, PostVote, Post, utcnow
from app.utils import get_request, gibberish, markdown_to_html, domain_from_url, validate_image from app.utils import get_request, gibberish, markdown_to_html, domain_from_url, validate_image
from sqlalchemy import desc, text from sqlalchemy import desc, text
import os import os
@ -59,7 +59,7 @@ def search_for_community(address: str):
ap_followers_url=community_json['followers'], ap_followers_url=community_json['followers'],
ap_inbox_url=community_json['endpoints']['sharedInbox'], ap_inbox_url=community_json['endpoints']['sharedInbox'],
ap_moderators_url=community_json['attributedTo'] if 'attributedTo' in community_json else None, ap_moderators_url=community_json['attributedTo'] if 'attributedTo' in community_json else None,
ap_fetched_at=datetime.utcnow(), ap_fetched_at=utcnow(),
ap_domain=server, ap_domain=server,
public_key=community_json['publicKey']['publicKeyPem'], public_key=community_json['publicKey']['publicKeyPem'],
# language=community_json['language'][0]['identifier'] # todo: language # language=community_json['language'][0]['identifier'] # todo: language

View file

@ -1,5 +1,4 @@
from datetime import datetime, timedelta, date from datetime import datetime, timedelta, date, timezone
from hashlib import md5
from time import time from time import time
from typing import List from typing import List
@ -20,6 +19,11 @@ from app.constants import SUBSCRIPTION_NONMEMBER, SUBSCRIPTION_MEMBER, SUBSCRIPT
SUBSCRIPTION_BANNED, SUBSCRIPTION_PENDING SUBSCRIPTION_BANNED, SUBSCRIPTION_PENDING
# same as datetime.utcnow() except with the UTC timezone explicitly added. datetime.utcnow() is depreciated in python 3.12+
def utcnow():
return datetime.now(timezone.utc)
class FullTextSearchQuery(BaseQuery, SearchQueryMixin): class FullTextSearchQuery(BaseQuery, SearchQueryMixin):
pass pass
@ -71,8 +75,8 @@ class Community(db.Model):
post_reply_count = db.Column(db.Integer, default=0) post_reply_count = db.Column(db.Integer, default=0)
nsfw = db.Column(db.Boolean, default=False) nsfw = db.Column(db.Boolean, default=False)
nsfl = db.Column(db.Boolean, default=False) nsfl = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
last_active = db.Column(db.DateTime, default=datetime.utcnow) last_active = db.Column(db.DateTime, default=utcnow)
public_key = db.Column(db.Text) public_key = db.Column(db.Text)
private_key = db.Column(db.Text) private_key = db.Column(db.Text)
@ -193,8 +197,8 @@ class User(UserMixin, db.Model):
keywords = db.Column(db.String(256)) keywords = db.Column(db.String(256))
show_nsfw = db.Column(db.Boolean, default=False) show_nsfw = db.Column(db.Boolean, default=False)
show_nsfl = db.Column(db.Boolean, default=False) show_nsfl = db.Column(db.Boolean, default=False)
created = db.Column(db.DateTime, default=datetime.utcnow) created = db.Column(db.DateTime, default=utcnow)
last_seen = db.Column(db.DateTime, default=datetime.utcnow, index=True) last_seen = db.Column(db.DateTime, default=utcnow, index=True)
avatar_id = db.Column(db.Integer, db.ForeignKey('file.id')) avatar_id = db.Column(db.Integer, db.ForeignKey('file.id'))
cover_id = db.Column(db.Integer, db.ForeignKey('file.id')) cover_id = db.Column(db.Integer, db.ForeignKey('file.id'))
public_key = db.Column(db.Text) public_key = db.Column(db.Text)
@ -307,12 +311,12 @@ class User(UserMixin, db.Model):
def expires_soon(self): def expires_soon(self):
if self.expires is None: if self.expires is None:
return False return False
return self.expires < datetime.utcnow() + timedelta(weeks=1) return self.expires < utcnow() + timedelta(weeks=1)
def is_expired(self): def is_expired(self):
if self.expires is None: if self.expires is None:
return True return True
return self.expires < datetime.utcnow() return self.expires < utcnow()
def expired_ages_ago(self): def expired_ages_ago(self):
if self.expires is None: if self.expires is None:
@ -347,7 +351,9 @@ class User(UserMixin, db.Model):
return self.ap_profile_id if self.ap_profile_id else f"https://{current_app.config['SERVER_NAME']}/u/{self.user_name}" return self.ap_profile_id if self.ap_profile_id else f"https://{current_app.config['SERVER_NAME']}/u/{self.user_name}"
def created_recently(self): def created_recently(self):
return self.created and self.created > datetime.utcnow() - timedelta(days=7) if self.created.tzinfo is None:
self.created = self.created.replace(tzinfo=timezone.utc)
return self.created and self.created > utcnow() - timedelta(days=7)
@staticmethod @staticmethod
def verify_reset_password_token(token): def verify_reset_password_token(token):
@ -394,7 +400,7 @@ class ActivityLog(db.Model):
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), index=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), index=True)
activity_type = db.Column(db.String(64)) activity_type = db.Column(db.String(64))
activity = db.Column(db.String(255)) activity = db.Column(db.String(255))
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) timestamp = db.Column(db.DateTime, index=True, default=utcnow)
class Post(db.Model): class Post(db.Model):
@ -420,9 +426,9 @@ class Post(db.Model):
notify_author = db.Column(db.Boolean, default=True) notify_author = db.Column(db.Boolean, default=True)
indexable = db.Column(db.Boolean, default=False) indexable = db.Column(db.Boolean, default=False)
from_bot = db.Column(db.Boolean, default=False) from_bot = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, index=True, default=datetime.utcnow) # this is when the content arrived here created_at = db.Column(db.DateTime, index=True, default=utcnow) # this is when the content arrived here
posted_at = db.Column(db.DateTime, index=True, default=datetime.utcnow) # this is when the original server created it posted_at = db.Column(db.DateTime, index=True, default=utcnow) # this is when the original server created it
last_active = db.Column(db.DateTime, index=True, default=datetime.utcnow) last_active = db.Column(db.DateTime, index=True, default=utcnow)
ip = db.Column(db.String(50)) ip = db.Column(db.String(50))
up_votes = db.Column(db.Integer, default=0) up_votes = db.Column(db.Integer, default=0)
down_votes = db.Column(db.Integer, default=0) down_votes = db.Column(db.Integer, default=0)
@ -492,8 +498,8 @@ class PostReply(db.Model):
nsfw = db.Column(db.Boolean, default=False) nsfw = db.Column(db.Boolean, default=False)
nsfl = db.Column(db.Boolean, default=False) nsfl = db.Column(db.Boolean, default=False)
notify_author = db.Column(db.Boolean, default=True) notify_author = db.Column(db.Boolean, default=True)
created_at = db.Column(db.DateTime, index=True, default=datetime.utcnow) created_at = db.Column(db.DateTime, index=True, default=utcnow)
posted_at = db.Column(db.DateTime, index=True, default=datetime.utcnow) posted_at = db.Column(db.DateTime, index=True, default=utcnow)
ip = db.Column(db.String(50)) ip = db.Column(db.String(50))
from_bot = db.Column(db.Boolean, default=False) from_bot = db.Column(db.Boolean, default=False)
up_votes = db.Column(db.Integer, default=0) up_votes = db.Column(db.Integer, default=0)
@ -548,13 +554,13 @@ class Domain(db.Model):
class DomainBlock(db.Model): class DomainBlock(db.Model):
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
domain_id = db.Column(db.Integer, db.ForeignKey('domain.id'), primary_key=True) domain_id = db.Column(db.Integer, db.ForeignKey('domain.id'), primary_key=True)
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
class CommunityBlock(db.Model): class CommunityBlock(db.Model):
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
community_id = db.Column(db.Integer, db.ForeignKey('community.id'), primary_key=True) community_id = db.Column(db.Integer, db.ForeignKey('community.id'), primary_key=True)
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
class CommunityMember(db.Model): class CommunityMember(db.Model):
@ -563,7 +569,7 @@ class CommunityMember(db.Model):
is_moderator = db.Column(db.Boolean, default=False) is_moderator = db.Column(db.Boolean, default=False)
is_owner = db.Column(db.Boolean, default=False) is_owner = db.Column(db.Boolean, default=False)
is_banned = db.Column(db.Boolean, default=False) is_banned = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
# people banned from communities # people banned from communities
@ -572,7 +578,7 @@ class CommunityBan(db.Model):
community_id = db.Column(db.Integer, db.ForeignKey('community.id'), primary_key=True) community_id = db.Column(db.Integer, db.ForeignKey('community.id'), primary_key=True)
banned_by = db.Column(db.Integer, db.ForeignKey('user.id')) banned_by = db.Column(db.Integer, db.ForeignKey('user.id'))
reason = db.Column(db.String(50)) reason = db.Column(db.String(50))
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
ban_until = db.Column(db.DateTime) ban_until = db.Column(db.DateTime)
@ -581,14 +587,14 @@ class UserNote(db.Model):
user_id = db.Column(db.Integer, db.ForeignKey('user.id')) user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
target_id = db.Column(db.Integer, db.ForeignKey('user.id')) target_id = db.Column(db.Integer, db.ForeignKey('user.id'))
body = db.Column(db.Text) body = db.Column(db.Text)
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
class UserBlock(db.Model): class UserBlock(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
blocker_id = db.Column(db.Integer, db.ForeignKey('user.id')) blocker_id = db.Column(db.Integer, db.ForeignKey('user.id'))
blocked_id = db.Column(db.Integer, db.ForeignKey('user.id')) blocked_id = db.Column(db.Integer, db.ForeignKey('user.id'))
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
class BannedInstances(db.Model): class BannedInstances(db.Model):
@ -596,13 +602,13 @@ class BannedInstances(db.Model):
domain = db.Column(db.String(256), index=True) domain = db.Column(db.String(256), index=True)
reason = db.Column(db.String(256)) reason = db.Column(db.String(256))
initiator = db.Column(db.String(256)) initiator = db.Column(db.String(256))
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
class AllowedInstances(db.Model): class AllowedInstances(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
domain = db.Column(db.String(256), index=True) domain = db.Column(db.String(256), index=True)
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
class Instance(db.Model): class Instance(db.Model):
@ -614,8 +620,8 @@ class Instance(db.Model):
vote_weight = db.Column(db.Float, default=1.0) vote_weight = db.Column(db.Float, default=1.0)
software = db.Column(db.String(50)) software = db.Column(db.String(50))
version = db.Column(db.String(50)) version = db.Column(db.String(50))
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=utcnow)
class Settings(db.Model): class Settings(db.Model):
@ -647,7 +653,7 @@ class PostVote(db.Model):
author_id = db.Column(db.Integer, db.ForeignKey('user.id')) author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
post_id = db.Column(db.Integer, db.ForeignKey('post.id')) post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
effect = db.Column(db.Float) effect = db.Column(db.Float)
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
post = db.relationship('Post', foreign_keys=[post_id]) post = db.relationship('Post', foreign_keys=[post_id])
@ -657,7 +663,7 @@ class PostReplyVote(db.Model):
author_id = db.Column(db.Integer, db.ForeignKey('user.id')) # the author of the reply voted on - who's reputation is affected author_id = db.Column(db.Integer, db.ForeignKey('user.id')) # the author of the reply voted on - who's reputation is affected
post_reply_id = db.Column(db.Integer, db.ForeignKey('post_reply.id')) post_reply_id = db.Column(db.Integer, db.ForeignKey('post_reply.id'))
effect = db.Column(db.Float) effect = db.Column(db.Float)
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
# save every activity to a log, to aid debugging # save every activity to a log, to aid debugging
@ -669,7 +675,7 @@ class ActivityPubLog(db.Model):
activity_json = db.Column(db.Text) # the full json of the activity activity_json = db.Column(db.Text) # the full json of the activity
result = db.Column(db.String(10)) # 'success' or 'failure' result = db.Column(db.String(10)) # 'success' or 'failure'
exception_message = db.Column(db.Text) exception_message = db.Column(db.Text)
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
class Filter(db.Model): class Filter(db.Model):
@ -707,7 +713,7 @@ class Notification(db.Model):
read = db.Column(db.Boolean, default=False) read = db.Column(db.Boolean, default=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id')) user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
author_id = db.Column(db.Integer, db.ForeignKey('user.id')) author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=utcnow)
@login.user_loader @login.user_loader

View file

@ -14,7 +14,7 @@ from app.community.forms import CreatePostForm
from app.post.util import post_replies, get_comment_branch, post_reply_count from app.post.util import post_replies, get_comment_branch, post_reply_count
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, POST_TYPE_LINK, POST_TYPE_ARTICLE, POST_TYPE_IMAGE from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, POST_TYPE_LINK, POST_TYPE_ARTICLE, POST_TYPE_IMAGE
from app.models import Post, PostReply, \ from app.models import Post, PostReply, \
PostReplyVote, PostVote, Notification PostReplyVote, PostVote, Notification, utcnow
from app.post import bp from app.post import bp
from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \ from app.utils import get_setting, render_template, allowlist_html, markdown_to_html, validation_required, \
shorten_string, markdown_to_text, domain_from_url, validate_image, gibberish, ap_datetime, return_304, \ shorten_string, markdown_to_text, domain_from_url, validate_image, gibberish, ap_datetime, return_304, \
@ -43,7 +43,7 @@ def show_post(post_id: int):
notification = Notification(title=_('Reply: ') + shorten_string(form.body.data), user_id=post.user_id, notification = Notification(title=_('Reply: ') + shorten_string(form.body.data), user_id=post.user_id,
author_id=current_user.id, url=url_for('activitypub.post_ap', post_id=post.id)) author_id=current_user.id, url=url_for('activitypub.post_ap', post_id=post.id))
db.session.add(notification) db.session.add(notification)
post.last_active = post.community.last_active = datetime.utcnow() post.last_active = post.community.last_active = utcnow()
post.reply_count += 1 post.reply_count += 1
post.community.post_reply_count += 1 post.community.post_reply_count += 1
@ -78,7 +78,7 @@ def show_post(post_id: int):
'content': reply.body, 'content': reply.body,
'mediaType': 'text/markdown' 'mediaType': 'text/markdown'
}, },
'published': ap_datetime(datetime.utcnow()), 'published': ap_datetime(utcnow()),
'distinguished': False, 'distinguished': False,
'audience': post.community.profile_id() 'audience': post.community.profile_id()
} }
@ -171,7 +171,7 @@ def post_vote(post_id: int, vote_direction):
effect=effect) effect=effect)
post.author.reputation += effect post.author.reputation += effect
db.session.add(vote) db.session.add(vote)
current_user.last_seen = datetime.utcnow() current_user.last_seen = utcnow()
db.session.commit() db.session.commit()
post.flush_cache() post.flush_cache()
return render_template('post/_post_voting_buttons.html', post=post, return render_template('post/_post_voting_buttons.html', post=post,
@ -223,7 +223,7 @@ def comment_vote(comment_id, vote_direction):
vote = PostReplyVote(user_id=current_user.id, post_reply_id=comment_id, author_id=comment.author.id, effect=effect) vote = PostReplyVote(user_id=current_user.id, post_reply_id=comment_id, author_id=comment.author.id, effect=effect)
comment.author.reputation += effect comment.author.reputation += effect
db.session.add(vote) db.session.add(vote)
current_user.last_seen = datetime.utcnow() current_user.last_seen = utcnow()
db.session.commit() db.session.commit()
comment.post.flush_cache() comment.post.flush_cache()
return render_template('post/_voting_buttons.html', comment=comment, return render_template('post/_voting_buttons.html', comment=comment,
@ -252,7 +252,7 @@ def add_reply(post_id: int, comment_id: int):
is_moderator = current_user.is_authenticated and any(mod.user_id == current_user.id for mod in mods) is_moderator = current_user.is_authenticated and any(mod.user_id == current_user.id for mod in mods)
form = NewReplyForm() form = NewReplyForm()
if form.validate_on_submit(): if form.validate_on_submit():
current_user.last_seen = datetime.utcnow() current_user.last_seen = utcnow()
reply = PostReply(user_id=current_user.id, post_id=post.id, parent_id=in_reply_to.id, depth=in_reply_to.depth + 1, reply = PostReply(user_id=current_user.id, post_id=post.id, parent_id=in_reply_to.id, depth=in_reply_to.depth + 1,
community_id=post.community.id, body=form.body.data, community_id=post.community.id, body=form.body.data,
body_html=markdown_to_html(form.body.data), body_html_safe=True, body_html=markdown_to_html(form.body.data), body_html_safe=True,
@ -270,7 +270,7 @@ def add_reply(post_id: int, comment_id: int):
effect=1.0) effect=1.0)
db.session.add(reply_vote) db.session.add(reply_vote)
post.reply_count = post_reply_count(post.id) post.reply_count = post_reply_count(post.id)
post.last_active = post.community.last_active = datetime.utcnow() post.last_active = post.community.last_active = utcnow()
db.session.commit() db.session.commit()
form.body.data = '' form.body.data = ''
flash('Your comment has been added.') flash('Your comment has been added.')
@ -299,7 +299,7 @@ def add_reply(post_id: int, comment_id: int):
'content': reply.body, 'content': reply.body,
'mediaType': 'text/markdown' 'mediaType': 'text/markdown'
}, },
'published': ap_datetime(datetime.utcnow()), 'published': ap_datetime(utcnow()),
'distinguished': False, 'distinguished': False,
'audience': post.community.profile_id(), 'audience': post.community.profile_id(),
'contentMap': { 'contentMap': {
@ -373,8 +373,8 @@ def post_edit(post_id: int):
if form.validate_on_submit(): if form.validate_on_submit():
save_post(form, post) save_post(form, post)
post.community.last_active = datetime.utcnow() post.community.last_active = utcnow()
post.edited_at = datetime.utcnow() post.edited_at = utcnow()
db.session.commit() db.session.commit()
post.flush_cache() post.flush_cache()
flash(_('Your changes have been saved.'), 'success') flash(_('Your changes have been saved.'), 'success')

View file

@ -5,7 +5,7 @@ from flask_login import login_user, logout_user, current_user, login_required
from flask_babel import _ from flask_babel import _
from app import db, cache from app import db, cache
from app.models import Post, Community, CommunityMember, User, PostReply, PostVote, Notification from app.models import Post, Community, CommunityMember, User, PostReply, PostVote, Notification, utcnow
from app.user import bp from app.user import bp
from app.user.forms import ProfileForm, SettingsForm from app.user.forms import ProfileForm, SettingsForm
from app.utils import get_setting, render_template, markdown_to_html, user_access, markdown_to_text, shorten_string from app.utils import get_setting, render_template, markdown_to_html, user_access, markdown_to_text, shorten_string
@ -210,7 +210,7 @@ def ban_purge_profile(actor):
def notifications(): def notifications():
"""Remove notifications older than 30 days""" """Remove notifications older than 30 days"""
db.session.query(Notification).filter( db.session.query(Notification).filter(
Notification.created_at < datetime.utcnow() - timedelta(days=30)).delete() Notification.created_at < utcnow() - timedelta(days=30)).delete()
db.session.commit() db.session.commit()
# Update unread notifications count # Update unread notifications count