2024-02-10 06:41:24 +13:00
import os . path
2024-01-03 20:14:39 +13:00
from datetime import datetime , timedelta
from math import log
2024-01-19 15:08:39 +13:00
from random import randint
2024-01-03 20:14:39 +13:00
2024-02-23 16:52:17 +13:00
import flask
2024-02-27 04:35:03 +13:00
import markdown2
2024-03-23 06:52:55 +13:00
import requests
2024-02-23 16:52:17 +13:00
from sqlalchemy . sql . operators import or_ , and_
2023-08-10 21:13:37 +12:00
2023-12-03 22:41:15 +13:00
from app import db , cache
2024-05-04 21:16:55 +01:00
from app . activitypub . util import make_image_sizes_async , refresh_user_profile , find_actor_or_create , \
2024-04-08 14:22:47 +02:00
refresh_community_profile_task , users_total , active_month , local_posts , local_communities , local_comments
2024-05-04 21:16:55 +01:00
from app . activitypub . signature import default_context
2024-01-11 20:52:09 +13:00
from app . constants import SUBSCRIPTION_PENDING , SUBSCRIPTION_MEMBER , POST_TYPE_IMAGE , POST_TYPE_LINK , \
2024-04-16 20:59:58 +12:00
SUBSCRIPTION_OWNER , SUBSCRIPTION_MODERATOR , POST_TYPE_VIDEO
2024-02-24 14:15:38 +13:00
from app . email import send_email , send_welcome_email
2024-01-19 15:08:39 +13:00
from app . inoculation import inoculation
2023-07-28 16:22:12 +12:00
from app . main import bp
2023-12-21 22:14:43 +13:00
from flask import g , session , flash , request , current_app , url_for , redirect , make_response , jsonify
2023-07-28 16:22:12 +12:00
from flask_moment import moment
2024-03-01 16:43:05 +13:00
from flask_login import current_user , login_required
2023-07-28 16:22:12 +12:00
from flask_babel import _ , get_locale
2024-01-07 13:35:36 +13:00
from sqlalchemy import select , desc , text
2023-09-05 20:25:02 +12:00
from sqlalchemy_searchable import search
2023-12-21 22:14:43 +13:00
from app . utils import render_template , get_setting , gibberish , request_etag_matches , return_304 , blocked_domains , \
2024-01-12 12:34:08 +13:00
ap_datetime , ip_address , retrieve_block_list , shorten_string , markdown_to_text , user_filters_home , \
2024-03-12 20:06:24 +13:00
joined_communities , moderating_communities , parse_page , theme_list , get_request , markdown_to_html , allowlist_html , \
2024-04-16 16:35:12 +12:00
blocked_instances , communities_banned_from , topic_tree , recently_upvoted_posts , recently_downvoted_posts , \
2024-04-26 12:54:12 +01:00
generate_image_from_video_url , blocked_users
2024-02-21 19:56:03 +13:00
from app . models import Community , CommunityMember , Post , Site , User , utcnow , Domain , Topic , File , Instance , \
InstanceRole , Notification
2024-01-13 18:18:32 +13:00
from PIL import Image
import pytesseract
2023-08-22 21:24:11 +12:00
2023-07-28 16:22:12 +12:00
2023-12-21 22:14:43 +13:00
@bp.route ( ' / ' , methods = [ ' HEAD ' , ' GET ' , ' POST ' ] )
2024-01-12 17:15:08 +13:00
@bp.route ( ' /home ' , methods = [ ' GET ' , ' POST ' ] )
@bp.route ( ' /home/<sort> ' , methods = [ ' GET ' , ' POST ' ] )
2024-01-15 18:26:22 +13:00
def index ( sort = None ) :
2023-12-21 22:14:43 +13:00
if ' application/ld+json ' in request . headers . get ( ' Accept ' , ' ' ) or ' application/activity+json ' in request . headers . get (
' Accept ' , ' ' ) :
return activitypub_application ( )
2024-01-12 17:15:08 +13:00
return home_page ( ' home ' , sort )
2023-08-22 21:24:11 +12:00
2024-01-12 17:15:08 +13:00
@bp.route ( ' /popular ' , methods = [ ' GET ' ] )
@bp.route ( ' /popular/<sort> ' , methods = [ ' GET ' ] )
2024-01-15 18:26:22 +13:00
def popular ( sort = None ) :
2024-01-12 17:15:08 +13:00
return home_page ( ' popular ' , sort )
2024-01-03 20:14:39 +13:00
2024-01-12 17:15:08 +13:00
@bp.route ( ' /all ' , methods = [ ' GET ' ] )
@bp.route ( ' /all/<sort> ' , methods = [ ' GET ' ] )
2024-01-15 18:26:22 +13:00
def all_posts ( sort = None ) :
2024-01-12 17:15:08 +13:00
return home_page ( ' all ' , sort )
2024-01-03 20:14:39 +13:00
2024-01-15 18:26:22 +13:00
def home_page ( type , sort ) :
2024-01-03 20:14:39 +13:00
verification_warning ( )
2024-01-15 18:26:22 +13:00
if sort is None :
sort = current_user . default_sort if current_user . is_authenticated else ' hot '
2024-01-03 20:14:39 +13:00
# If nothing has changed since their last visit, return HTTP 304
2024-01-15 18:26:22 +13:00
current_etag = f " { type } _ { sort } _ { hash ( str ( g . site . last_active ) ) } "
2024-01-03 20:14:39 +13:00
if current_user . is_anonymous and request_etag_matches ( current_etag ) :
return return_304 ( current_etag )
page = request . args . get ( ' page ' , 1 , type = int )
2024-02-13 21:28:33 +13:00
low_bandwidth = request . cookies . get ( ' low_bandwidth ' , ' 0 ' ) == ' 1 '
2024-01-03 20:14:39 +13:00
if current_user . is_anonymous :
2024-01-12 17:15:08 +13:00
flash ( _ ( ' Create an account to tailor this feed to your interests. ' ) )
2024-01-03 20:14:39 +13:00
posts = Post . query . filter ( Post . from_bot == False , Post . nsfw == False , Post . nsfl == False )
2024-01-12 17:15:08 +13:00
posts = posts . join ( Community , Community . id == Post . community_id )
if type == ' home ' :
posts = posts . filter ( Community . show_home == True )
elif type == ' popular ' :
posts = posts . filter ( Community . show_popular == True ) . filter ( Post . score > 100 )
elif type == ' all ' :
posts = posts . filter ( Community . show_all == True )
2024-01-11 20:39:22 +13:00
content_filters = { }
2024-01-03 20:14:39 +13:00
else :
2024-01-12 17:15:08 +13:00
if type == ' home ' :
posts = Post . query . join ( CommunityMember , Post . community_id == CommunityMember . community_id ) . filter (
CommunityMember . is_banned == False )
# posts = posts.join(User, CommunityMember.user_id == User.id).filter(User.id == current_user.id)
posts = posts . filter ( CommunityMember . user_id == current_user . id )
elif type == ' popular ' :
posts = Post . query . filter ( Post . from_bot == False )
posts = posts . join ( Community , Community . id == Post . community_id )
posts = posts . filter ( Community . show_popular == True , Post . score > 100 )
elif type == ' all ' :
posts = Post . query
posts = posts . join ( Community , Community . id == Post . community_id )
posts = posts . filter ( Community . show_all == True )
2024-02-01 11:59:09 +13:00
if current_user . ignore_bots :
posts = posts . filter ( Post . from_bot == False )
if current_user . show_nsfl is False :
posts = posts . filter ( Post . nsfl == False )
if current_user . show_nsfw is False :
posts = posts . filter ( Post . nsfw == False )
2024-01-03 20:14:39 +13:00
domains_ids = blocked_domains ( current_user . id )
if domains_ids :
posts = posts . filter ( or_ ( Post . domain_id . not_in ( domains_ids ) , Post . domain_id == None ) )
2024-03-12 20:06:24 +13:00
instance_ids = blocked_instances ( current_user . id )
if instance_ids :
posts = posts . filter ( or_ ( Post . instance_id . not_in ( instance_ids ) , Post . instance_id == None ) )
2024-04-26 12:54:12 +01:00
# filter blocked users
blocked_accounts = blocked_users ( current_user . id )
if blocked_accounts :
posts = posts . filter ( Post . user_id . not_in ( blocked_accounts ) )
2024-01-11 20:39:22 +13:00
content_filters = user_filters_home ( current_user . id )
2024-01-03 20:14:39 +13:00
2024-01-12 17:15:08 +13:00
# Sorting
if sort == ' hot ' :
2024-02-21 19:56:03 +13:00
posts = posts . order_by ( desc ( Post . ranking ) ) . order_by ( desc ( Post . posted_at ) )
2024-01-12 17:15:08 +13:00
elif sort == ' top ' :
2024-04-14 07:59:24 +12:00
posts = posts . filter ( Post . posted_at > utcnow ( ) - timedelta ( days = 1 ) ) . order_by ( desc ( Post . up_votes - Post . down_votes ) )
2024-01-12 17:15:08 +13:00
elif sort == ' new ' :
posts = posts . order_by ( desc ( Post . posted_at ) )
2024-01-15 18:26:22 +13:00
elif sort == ' active ' :
posts = posts . order_by ( desc ( Post . last_active ) )
2024-01-12 17:15:08 +13:00
# Pagination
2024-02-13 21:28:33 +13:00
posts = posts . paginate ( page = page , per_page = 100 if current_user . is_authenticated and not low_bandwidth else 50 , error_out = False )
2024-01-12 17:15:08 +13:00
if type == ' home ' :
next_url = url_for ( ' main.index ' , page = posts . next_num , sort = sort ) if posts . has_next else None
prev_url = url_for ( ' main.index ' , page = posts . prev_num , sort = sort ) if posts . has_prev and page != 1 else None
elif type == ' popular ' :
next_url = url_for ( ' main.popular ' , page = posts . next_num , sort = sort ) if posts . has_next else None
prev_url = url_for ( ' main.popular ' , page = posts . prev_num , sort = sort ) if posts . has_prev and page != 1 else None
elif type == ' all ' :
next_url = url_for ( ' main.all_posts ' , page = posts . next_num , sort = sort ) if posts . has_next else None
prev_url = url_for ( ' main.all_posts ' , page = posts . prev_num , sort = sort ) if posts . has_prev and page != 1 else None
2024-01-03 20:14:39 +13:00
2024-03-21 21:19:50 +13:00
# Active Communities
active_communities = Community . query . filter_by ( banned = False )
if current_user . is_authenticated : # do not show communities current user is banned from
banned_from = communities_banned_from ( current_user . id )
if banned_from :
active_communities = active_communities . filter ( Community . id . not_in ( banned_from ) )
active_communities = active_communities . order_by ( desc ( Community . last_active ) ) . limit ( 5 ) . all ( )
2024-01-03 20:14:39 +13:00
2024-04-11 14:04:57 +12:00
# Voting history
if current_user . is_authenticated :
recently_upvoted = recently_upvoted_posts ( current_user . id )
recently_downvoted = recently_downvoted_posts ( current_user . id )
else :
recently_upvoted = [ ]
recently_downvoted = [ ]
2024-01-12 17:15:08 +13:00
return render_template ( ' index.html ' , posts = posts , active_communities = active_communities , show_post_community = True ,
2024-04-16 20:59:58 +12:00
POST_TYPE_IMAGE = POST_TYPE_IMAGE , POST_TYPE_LINK = POST_TYPE_LINK , POST_TYPE_VIDEO = POST_TYPE_VIDEO ,
2024-04-11 14:04:57 +12:00
low_bandwidth = low_bandwidth , recently_upvoted = recently_upvoted ,
recently_downvoted = recently_downvoted ,
2024-01-03 20:14:39 +13:00
SUBSCRIPTION_PENDING = SUBSCRIPTION_PENDING , SUBSCRIPTION_MEMBER = SUBSCRIPTION_MEMBER ,
2024-01-15 18:26:22 +13:00
etag = f " { type } _ { sort } _ { hash ( str ( g . site . last_active ) ) } " , next_url = next_url , prev_url = prev_url ,
2024-02-27 06:49:37 +13:00
#rss_feed=f"https://{current_app.config['SERVER_NAME']}/feed",
#rss_feed_name=f"Posts on " + g.site.name,
2024-01-12 17:15:08 +13:00
title = f " { g . site . name } - { g . site . description } " ,
description = shorten_string ( markdown_to_text ( g . site . sidebar ) , 150 ) ,
content_filters = content_filters , type = type , sort = sort ,
moderating_communities = moderating_communities ( current_user . get_id ( ) ) ,
2024-01-19 15:08:39 +13:00
joined_communities = joined_communities ( current_user . get_id ( ) ) ,
inoculation = inoculation [ randint ( 0 , len ( inoculation ) - 1 ) ] )
2024-01-12 12:34:08 +13:00
@bp.route ( ' /topics ' , methods = [ ' GET ' ] )
def list_topics ( ) :
verification_warning ( )
2024-04-08 19:48:25 +12:00
topics = topic_tree ( )
2024-01-12 12:34:08 +13:00
return render_template ( ' list_topics.html ' , topics = topics , title = _ ( ' Browse by topic ' ) ,
2024-01-22 21:14:40 +13:00
low_bandwidth = request . cookies . get ( ' low_bandwidth ' , ' 0 ' ) == ' 1 ' ,
moderating_communities = moderating_communities ( current_user . get_id ( ) ) ,
2024-01-12 12:34:08 +13:00
joined_communities = joined_communities ( current_user . get_id ( ) ) )
2024-01-03 20:14:39 +13:00
2023-08-22 21:24:11 +12:00
@bp.route ( ' /communities ' , methods = [ ' GET ' ] )
def list_communities ( ) :
2023-10-23 13:03:35 +13:00
verification_warning ( )
2023-09-05 20:25:02 +12:00
search_param = request . args . get ( ' search ' , ' ' )
2024-01-04 16:00:19 +13:00
topic_id = int ( request . args . get ( ' topic_id ' , 0 ) )
2024-01-07 21:53:35 +13:00
sort_by = text ( ' community. ' + request . args . get ( ' sort_by ' ) if request . args . get ( ' sort_by ' ) else ' community.post_reply_count desc ' )
2024-01-04 16:00:19 +13:00
topics = Topic . query . order_by ( Topic . name ) . all ( )
2024-02-02 15:57:22 +13:00
communities = Community . query . filter_by ( banned = False )
2023-09-05 20:25:02 +12:00
if search_param == ' ' :
2024-01-04 16:00:19 +13:00
pass
2023-09-05 20:25:02 +12:00
else :
2024-02-02 15:57:22 +13:00
communities = communities . filter ( or_ ( Community . title . ilike ( f " % { search_param } % " ) , Community . ap_id . ilike ( f " % { search_param } % " ) ) )
2024-01-04 16:00:19 +13:00
#query = search(select(Community), search_param, sort=True) # todo: exclude banned communities from search
#communities = db.session.scalars(query).all()
2024-02-02 15:57:22 +13:00
2024-01-04 16:00:19 +13:00
if topic_id != 0 :
communities = communities . filter_by ( topic_id = topic_id )
2023-09-05 20:25:02 +12:00
2024-03-21 21:19:50 +13:00
if current_user . is_authenticated :
banned_from = communities_banned_from ( current_user . id )
if banned_from :
communities = communities . filter ( Community . id . not_in ( banned_from ) )
2024-01-07 13:35:36 +13:00
return render_template ( ' list_communities.html ' , communities = communities . order_by ( sort_by ) . all ( ) , search = search_param , title = _ ( ' Communities ' ) ,
2023-12-17 00:12:49 +13:00
SUBSCRIPTION_PENDING = SUBSCRIPTION_PENDING , SUBSCRIPTION_MEMBER = SUBSCRIPTION_MEMBER ,
2024-01-11 20:52:09 +13:00
SUBSCRIPTION_OWNER = SUBSCRIPTION_OWNER , SUBSCRIPTION_MODERATOR = SUBSCRIPTION_MODERATOR ,
topics = topics , topic_id = topic_id , sort_by = sort_by ,
2024-01-12 12:34:08 +13:00
low_bandwidth = request . cookies . get ( ' low_bandwidth ' , ' 0 ' ) == ' 1 ' , moderating_communities = moderating_communities ( current_user . get_id ( ) ) ,
joined_communities = joined_communities ( current_user . get_id ( ) ) )
2023-09-05 20:25:02 +12:00
@bp.route ( ' /communities/local ' , methods = [ ' GET ' ] )
def list_local_communities ( ) :
2023-10-23 13:03:35 +13:00
verification_warning ( )
2024-01-07 22:45:09 +13:00
sort_by = text ( ' community. ' + request . args . get ( ' sort_by ' ) if request . args . get ( ' sort_by ' ) else ' community.post_reply_count desc ' )
communities = Community . query . filter_by ( ap_id = None , banned = False )
return render_template ( ' list_communities.html ' , communities = communities . order_by ( sort_by ) . all ( ) , title = _ ( ' Local communities ' ) , sort_by = sort_by ,
2024-01-08 19:41:32 +13:00
SUBSCRIPTION_PENDING = SUBSCRIPTION_PENDING , SUBSCRIPTION_MEMBER = SUBSCRIPTION_MEMBER ,
2024-03-03 22:09:38 +00:00
SUBSCRIPTION_OWNER = SUBSCRIPTION_OWNER , SUBSCRIPTION_MODERATOR = SUBSCRIPTION_MODERATOR ,
2024-01-12 12:34:08 +13:00
low_bandwidth = request . cookies . get ( ' low_bandwidth ' , ' 0 ' ) == ' 1 ' , moderating_communities = moderating_communities ( current_user . get_id ( ) ) ,
joined_communities = joined_communities ( current_user . get_id ( ) ) )
2023-09-05 20:25:02 +12:00
@bp.route ( ' /communities/subscribed ' , methods = [ ' GET ' ] )
def list_subscribed_communities ( ) :
2023-10-23 13:03:35 +13:00
verification_warning ( )
2024-01-07 22:45:09 +13:00
sort_by = text ( ' community. ' + request . args . get ( ' sort_by ' ) if request . args . get ( ' sort_by ' ) else ' community.post_reply_count desc ' )
2024-01-05 14:09:46 +13:00
if current_user . is_authenticated :
2024-02-23 20:23:59 +13:00
communities = Community . query . filter_by ( banned = False ) . join ( CommunityMember ) . filter ( CommunityMember . user_id == current_user . id ) . order_by ( sort_by ) . all ( )
2024-01-05 14:09:46 +13:00
else :
communities = [ ]
2024-02-23 20:23:59 +13:00
return render_template ( ' list_communities.html ' , communities = communities , title = _ ( ' Joined communities ' ) ,
2024-01-08 19:41:32 +13:00
SUBSCRIPTION_PENDING = SUBSCRIPTION_PENDING , SUBSCRIPTION_MEMBER = SUBSCRIPTION_MEMBER , sort_by = sort_by ,
2024-03-03 22:09:38 +00:00
SUBSCRIPTION_OWNER = SUBSCRIPTION_OWNER , SUBSCRIPTION_MODERATOR = SUBSCRIPTION_MODERATOR ,
2024-01-12 12:34:08 +13:00
low_bandwidth = request . cookies . get ( ' low_bandwidth ' , ' 0 ' ) == ' 1 ' , moderating_communities = moderating_communities ( current_user . get_id ( ) ) ,
joined_communities = joined_communities ( current_user . get_id ( ) ) )
2023-12-03 22:41:15 +13:00
2024-01-05 16:14:55 +13:00
@bp.route ( ' /donate ' )
def donate ( ) :
return render_template ( ' donate.html ' )
2024-04-01 13:05:09 +02:00
@bp.route ( ' /about ' )
def about_page ( ) :
2024-04-08 14:22:47 +02:00
user_amount = users_total ( )
MAU = active_month ( )
posts_amount = local_posts ( )
admins = db . session . execute ( text ( ' SELECT user_name, email FROM " user " WHERE " id " IN (SELECT " user_id " FROM " user_role " WHERE " role_id " = 4) ORDER BY id ' ) ) . all ( )
staff = db . session . execute ( text ( ' SELECT user_name FROM " user " WHERE " id " IN (SELECT " user_id " FROM " user_role " WHERE " role_id " = 2) ORDER BY id ' ) ) . all ( )
domains_amount = db . session . execute ( text ( ' SELECT COUNT(id) as c FROM " domain " WHERE " banned " IS false ' ) ) . scalar ( )
community_amount = local_communities ( )
2024-04-01 13:05:09 +02:00
instance = Instance . query . filter_by ( id = 1 ) . first ( )
2024-04-08 14:22:47 +02:00
return render_template ( ' about.html ' , user_amount = user_amount , mau = MAU , posts_amount = posts_amount , domains_amount = domains_amount , community_amount = community_amount , instance = instance , admins = admins , staff = staff )
2024-04-01 13:05:09 +02:00
2024-01-05 16:14:55 +13:00
@bp.route ( ' /privacy ' )
def privacy ( ) :
return render_template ( ' privacy.html ' )
2023-12-17 00:12:49 +13:00
@bp.route ( ' /login ' )
def login ( ) :
return redirect ( url_for ( ' auth.login ' ) )
@bp.route ( ' /robots.txt ' )
def robots ( ) :
resp = make_response ( render_template ( ' robots.txt ' ) )
resp . mimetype = ' text/plain '
return resp
2024-01-24 17:02:48 +13:00
@bp.route ( ' /sitemap.xml ' )
@cache.cached ( timeout = 6000 )
def sitemap ( ) :
posts = Post . query . filter ( Post . from_bot == False )
posts = posts . join ( Community , Community . id == Post . community_id )
posts = posts . filter ( Community . show_all == True , Community . ap_id == None ) # sitemap.xml only includes local posts
if not g . site . enable_nsfw :
posts = posts . filter ( Community . nsfw == False )
if not g . site . enable_nsfl :
posts = posts . filter ( Community . nsfl == False )
posts = posts . order_by ( desc ( Post . posted_at ) )
resp = make_response ( render_template ( ' sitemap.xml ' , posts = posts , current_app = current_app ) )
resp . mimetype = ' text/xml '
return resp
2024-01-21 12:14:05 +13:00
@bp.route ( ' /keyboard_shortcuts ' )
def keyboard_shortcuts ( ) :
return render_template ( ' keyboard_shortcuts.html ' )
2024-02-10 12:20:18 +13:00
def list_files ( directory ) :
for root , dirs , files in os . walk ( directory ) :
for file in files :
yield os . path . join ( root , file )
2023-12-03 22:41:15 +13:00
@bp.route ( ' /test ' )
def test ( ) :
2024-04-18 13:57:33 +12:00
2024-04-09 13:12:10 +12:00
md = " ::: spoiler I ' m all for ya having fun and your right to hurt yourself. \n \n I am a former racer, commuter, and professional Buyer for a chain of bike shops. I ' m also disabled from the crash involving the 6th and 7th cars that have hit me in the last 170k+ miles of riding. I only barely survived what I simplify as a \" broken neck and back. \" Cars making U-turns are what will get you if you ride long enough, \n \n especially commuting. It will look like just another person turning in front of you, you ' ll compensate like usual, and before your brain can even register what is really happening, what was your normal escape route will close and you ' re going to crash really hard. It is the only kind of crash that your intuition is useless against. \n ::: "
return markdown_to_html ( md )
2024-02-24 14:15:38 +13:00
2024-02-23 16:52:17 +13:00
users_to_notify = User . query . join ( Notification , User . id == Notification . user_id ) . filter (
User . ap_id == None ,
Notification . created_at > User . last_seen ,
Notification . read == False ,
User . email_unread_sent == False , # they have not been emailed since last activity
User . email_unread == True # they want to be emailed
) . all ( )
for user in users_to_notify :
notifications = Notification . query . filter ( Notification . user_id == user . id , Notification . read == False ,
Notification . created_at > user . last_seen ) . all ( )
if notifications :
# Also get the top 20 posts since their last login
posts = Post . query . join ( CommunityMember , Post . community_id == CommunityMember . community_id ) . filter (
CommunityMember . is_banned == False )
posts = posts . filter ( CommunityMember . user_id == user . id )
if user . ignore_bots :
posts = posts . filter ( Post . from_bot == False )
if user . show_nsfl is False :
posts = posts . filter ( Post . nsfl == False )
if user . show_nsfw is False :
posts = posts . filter ( Post . nsfw == False )
domains_ids = blocked_domains ( user . id )
if domains_ids :
posts = posts . filter ( or_ ( Post . domain_id . not_in ( domains_ids ) , Post . domain_id == None ) )
posts = posts . filter ( Post . posted_at > user . last_seen ) . order_by ( desc ( Post . score ) )
posts = posts . limit ( 20 ) . all ( )
# Send email!
2024-02-24 13:33:28 +13:00
send_email ( _ ( ' [PieFed] You have unread notifications ' ) ,
sender = f ' PieFed <noreply@ { current_app . config [ " SERVER_NAME " ] } > ' ,
2024-02-23 16:52:17 +13:00
recipients = [ user . email ] ,
text_body = flask . render_template ( ' email/unread_notifications.txt ' , user = user , notifications = notifications ) ,
html_body = flask . render_template ( ' email/unread_notifications.html ' , user = user ,
notifications = notifications ,
posts = posts ,
domain = current_app . config [ ' SERVER_NAME ' ] ) )
user . email_unread_sent = True
db . session . commit ( )
2024-02-19 15:01:53 +13:00
return ' ok '
2023-10-23 13:03:35 +13:00
2024-03-01 16:43:05 +13:00
@bp.route ( ' /test_email ' )
@login_required
def test_email ( ) :
send_email ( ' This is a test email ' , f ' { g . site . name } < { current_app . config [ " MAIL_FROM " ] } > ' , [ current_user . email ] ,
' This is a test email. If you received this, email sending is working! ' ,
' <p>This is a test email. If you received this, email sending is working!</p> ' )
return f ' Email sent to { current_user . email } . '
2024-04-12 10:52:15 +12:00
@bp.route ( ' /find_voters ' )
def find_voters ( ) :
user_ids = db . session . execute ( text ( ' SELECT id from " user " ORDER BY last_seen DESC LIMIT 5000 ' ) ) . scalars ( )
voters = { }
for user_id in user_ids :
recently_downvoted = recently_downvoted_posts ( user_id )
if len ( recently_downvoted ) > 10 :
voters [ user_id ] = str ( recently_downvoted )
return str ( find_duplicate_values ( voters ) )
def find_duplicate_values ( dictionary ) :
# Create a dictionary to store the keys for each value
value_to_keys = { }
# Iterate through the input dictionary
for key , value in dictionary . items ( ) :
# If the value is not already in the dictionary, add it
if value not in value_to_keys :
value_to_keys [ value ] = [ key ]
else :
# If the value is already in the dictionary, append the key to the list
value_to_keys [ value ] . append ( key )
# Filter out the values that have only one key (i.e., unique values)
duplicates = { value : keys for value , keys in value_to_keys . items ( ) if len ( keys ) > 1 }
return duplicates
2023-10-23 13:03:35 +13:00
def verification_warning ( ) :
if hasattr ( current_user , ' verified ' ) and current_user . verified is False :
flash ( _ ( ' Please click the link in your email inbox to verify your account. ' ) , ' warning ' )
2023-12-21 22:14:43 +13:00
2023-12-24 13:28:41 +13:00
@cache.cached ( timeout = 6 )
2023-12-21 22:14:43 +13:00
def activitypub_application ( ) :
application_data = {
' @context ' : default_context ( ) ,
' type ' : ' Application ' ,
' id ' : f " https:// { current_app . config [ ' SERVER_NAME ' ] } / " ,
2024-03-24 15:35:45 +13:00
' name ' : ' PieFed ' ,
' summary ' : g . site . name + ' - ' + g . site . description ,
2023-12-21 22:14:43 +13:00
' published ' : ap_datetime ( g . site . created_at ) ,
' updated ' : ap_datetime ( g . site . updated ) ,
' inbox ' : f " https:// { current_app . config [ ' SERVER_NAME ' ] } /site_inbox " ,
' outbox ' : f " https:// { current_app . config [ ' SERVER_NAME ' ] } /site_outbox " ,
}
resp = jsonify ( application_data )
resp . content_type = ' application/activity+json '
return resp