@@ -258,22 +258,108 @@ defmodule Ftpdb.DB do
258258 end )
259259 end
260260
261- def random_projects ( limit \\ 10 ) do
261+ defp get_max_project_id do
262262 { :ok , response } =
263- client ( )
264- |> Supabase.PostgREST . rpc ( "get_random_projects" , % { limit_count: limit } )
263+ Supabase.PostgREST . from ( client ( ) , "projects" )
264+ |> Supabase.PostgREST . select ( [ "id" ] )
265+ |> Supabase.PostgREST . order ( "id" , desc: true )
266+ |> Supabase.PostgREST . limit ( 1 )
267+ |> Map . put ( :method , :get )
265268 |> Supabase.PostgREST . execute ( )
266269
267- response . body
268- |> Enum . map ( fn item ->
269- total_hours = item [ "stat_total_hours" ] || 0
270- duration = item [ "stat_total_duration_seconds" ] || total_hours * 3600
270+ case response . body do
271+ [ % { "id" => max_id } ] -> max_id
272+ _ -> 0
273+ end
274+ end
271275
272- item
273- |> Map . drop ( [ "stat_total_duration_seconds" ] )
274- |> Map . put ( "total_duration_seconds" , duration )
275- |> Map . put ( "total_hours" , total_hours )
276- end )
276+ defp fetch_and_format_project_for_random ( id ) do
277+ result =
278+ Supabase.PostgREST . from ( client ( ) , "projects" )
279+ |> Supabase.PostgREST . select ( [
280+ "id" ,
281+ "title" ,
282+ "banner_url" ,
283+ "stat_total_duration_seconds" ,
284+ "stat_hot_score" ,
285+ "stat_total_likes"
286+ ] )
287+ |> Supabase.PostgREST . eq ( "id" , id )
288+ |> Map . put ( :method , :get )
289+ |> Supabase.PostgREST . execute ( )
290+
291+ case result do
292+ { :ok , % { body: [ item ] } } when not is_nil ( item ) ->
293+ banner_url = item [ "banner_url" ]
294+
295+ if is_nil ( banner_url ) or
296+ banner_url == "https://flavortown.hackclub.com/assets/default-banner-3d4e1b67.png" do
297+ nil
298+ else
299+ user_id = get_user_id ( item [ "id" ] )
300+
301+ { user_avatar , user_display_name } =
302+ if user_id do
303+ case get_user_info ( user_id ) do
304+ [ u ] -> { u . avatar_url , u . display_name || "Unknown User" }
305+ _ -> { nil , "Unknown User" }
306+ end
307+ else
308+ { nil , "Unknown User" }
309+ end
310+
311+ duration = item [ "stat_total_duration_seconds" ] || 0
312+
313+ % {
314+ id: to_string ( item [ "id" ] ) ,
315+ title: item [ "title" ] ,
316+ banner_url: banner_url ,
317+ display_name: user_display_name ,
318+ avatar_url: user_avatar ,
319+ stat_hot_score: item [ "stat_hot_score" ] || 0 ,
320+ stat_total_likes: item [ "stat_total_likes" ] || 0 ,
321+ total_duration_seconds: duration ,
322+ total_hours: div ( duration , 3600 )
323+ }
324+ end
325+
326+ _ ->
327+ nil
328+ end
329+ end
330+
331+ def random_projects ( limit \\ 10 ) do
332+ max_id = get_max_project_id ( )
333+
334+ if max_id == 0 do
335+ [ ]
336+ else
337+ random_ids =
338+ 1 .. ( limit * 10 )
339+ |> Enum . map ( fn _ -> :rand . uniform ( max_id ) end )
340+ |> Enum . uniq ( )
341+
342+ random_ids
343+ |> Enum . reduce_while ( [ ] , fn id , acc ->
344+ if length ( acc ) >= limit do
345+ { :halt , acc }
346+ else
347+ project =
348+ Cachex . fetch! (
349+ :random_project_cache ,
350+ to_string ( id ) ,
351+ fn _key -> fetch_and_format_project_for_random ( id ) end ,
352+ expiration: :timer . minutes ( 30 )
353+ )
354+
355+ if project do
356+ { :cont , [ project | acc ] }
357+ else
358+ { :cont , acc }
359+ end
360+ end
361+ end )
362+ end
277363 end
278364
279365 def search_projects ( query ) when is_binary ( query ) do
0 commit comments