• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hicommonwealth / commonwealth / 14475911829

15 Apr 2025 05:42PM UTC coverage: 46.141% (-0.1%) from 46.287%
14475911829

Pull #11664

github

web-flow
Merge 7d47d0054 into 84ecac07e
Pull Request #11664: Added `XpChainEventCreated` support

1622 of 3876 branches covered (41.85%)

Branch coverage included in aggregate %.

0 of 25 new or added lines in 2 files covered. (0.0%)

58 existing lines in 14 files now uncovered.

2976 of 6089 relevant lines covered (48.88%)

39.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/libs/model/src/utils/getUserActivityFeed.ts
1
import * as schemas from '@hicommonwealth/schemas';
2
import { CommunityTierMap } from '@hicommonwealth/shared';
3
import { QueryTypes } from 'sequelize';
4
import { z } from 'zod';
5
import { models } from '../database';
6

7
/**
8
 * Gets last updated threads and their recent comments
9
 * @param user_id by user id communities, 0 for global
10
 * @param limit thread limit
11
 * @param comment_limit comment limit
12
 */
13

14
type GetUserActivityFeedParams = z.infer<typeof schemas.ActivityFeed.input> & {
15
  user_id?: number;
16
};
17

18
export async function getUserActivityFeed({
19
  user_id = 0,
×
20
  comment_limit,
21
  limit,
22
  cursor,
23
}: GetUserActivityFeedParams) {
24
  const offset = (cursor - 1) * limit;
×
UNCOV
25
  const query = `
×
26
WITH 
27
user_communities AS (
28
    SELECT DISTINCT community_id 
29
    FROM "Addresses" 
30
    WHERE user_id = :user_id
31
),
32
top_threads AS (
33
  SELECT T.*, count(*) OVER() AS total, C.icon_url
34
  FROM "Threads" T
35
  ${
36
    user_id
×
37
      ? 'JOIN user_communities UC ON UC.community_id = T.community_id'
38
      : ''
39
  }
40
  JOIN "Communities" C ON C.id = T.community_id
41
  WHERE T.deleted_at IS NULL 
42
      AND T.marked_as_spam_at IS NULL 
43
      AND C.active IS TRUE 
44
      AND C.tier != ${CommunityTierMap.SpamCommunity}
45
      AND C.id NOT IN ('ethereum', 'cosmos', 'polkadot')
46
  ORDER BY T.activity_rank_date DESC NULLS LAST
47
  LIMIT :limit OFFSET :offset 
48
)
49

50
SELECT 
51
  jsonb_set(
52
    jsonb_build_object(
53
      'community_id', T.community_id,
54
      'community_icon', T.icon_url,
55
      'id', T.id,
56
      'user_id', U.id,
57
      'user_tier', U.tier,
58
      'user_address', A.address,
59
      'profile_name', U.profile->>'name',
60
      'profile_avatar', U.profile->>'avatar_url',
61
      'body', T.body,
62
      'content_url', T.content_url,
63
      'title', T.title,
64
      'kind', T.kind,
65
      'stage', T.stage,
66
      'number_of_comments', coalesce(T.comment_count, 0),
67
      'created_at', T.created_at::text,
68
      'updated_at', T.updated_at::text,
69
      'deleted_at', T.deleted_at::text,
70
      'locked_at', T.locked_at::text,
71
      'archived_at', T.archived_at::text,
72
      'marked_as_spam_at', T.marked_as_spam_at::text,
73
      'read_only', T.read_only,
74
      'has_poll', T.has_poll,
75
      'discord_meta', T.discord_meta,
76
      'is_linking_token', T.is_linking_token,
77
      'topic', jsonb_build_object(
78
        'id', T.topic_id,
79
        'name', Tp.name,
80
        'description', Tp.description
81
      )
82
    ),
83
    '{recent_comments}', 
84
    COALESCE(
85
      (SELECT jsonb_agg(jsonb_strip_nulls(jsonb_build_object(
86
        'id', C.id,
87
        'address', C.address,
88
        'user_id', C.user_id,
89
        'user_tier', C.user_tier,
90
        'profile_name', C.profile_name,
91
        'profile_avatar', C.profile_avatar,
92
        'body', C.body,
93
        'content_url', C.content_url,
94
        'created_at', C.created_at::text,
95
        'updated_at', C.updated_at::text,
96
        'deleted_at', C.deleted_at::text,
97
        'marked_as_spam_at', C.marked_as_spam_at::text,
98
        'discord_meta', C.discord_meta
99
      )) ORDER BY C.created_at DESC)
100
      FROM (
101
          SELECT 
102
            C.*,
103
            A.address,
104
            U.id as user_id,
105
            U.tier as user_tier,
106
            U.profile->>'name' as profile_name, 
107
            U.profile->>'avatar_url' as profile_avatar, 
108
            ROW_NUMBER() OVER (PARTITION BY C.thread_id ORDER BY C.created_at DESC) AS rn
109
          FROM "Comments" C
110
            JOIN "Addresses" A on C.address_id = A.id
111
            JOIN "Users" U on A.user_id = U.id
112
          WHERE 
113
            C.thread_id = T.id 
114
            AND C.deleted_at IS NULL
115
      ) C WHERE C.rn <= :comment_limit), '[]')
116
  ) AS thread,
117
  T.total 
118
FROM
119
  top_threads T
120
  JOIN "Addresses" A ON A.id = T.address_id AND A.community_id = T.community_id
121
  JOIN "Users" U ON U.id = A.user_id
122
  JOIN "Topics" Tp ON Tp.id = T.topic_id
123
ORDER BY
124
  T.activity_rank_date DESC NULLS LAST
125
  `;
126

UNCOV
127
  const threads = await models.sequelize.query<
×
128
    z.infer<typeof schemas.ActivityThreadWrapper> & { total?: number }
129
  >(query, {
130
    type: QueryTypes.SELECT,
131
    raw: true,
132
    replacements: { user_id, limit, comment_limit, offset },
133
  });
134

UNCOV
135
  const formattedThreads = threads.map((item) => ({
×
136
    ...item?.thread,
137
  }));
UNCOV
138
  return schemas.buildPaginatedResponse(
×
139
    formattedThreads,
140
    +(threads.at(0)?.total ?? 0),
×
141
    {
142
      limit,
143
      offset,
144
    },
145
  );
146
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc