Discourse, создание своих наград

discourse
ruby
программирование

(Евгений) #1

Запросы (sql) для наград в Discourse не представляются администраторам, по умолчанию.

Это было сделано по нескольким причинам:

  • Безопасность: позволить администраторам вводить SQL напрямую это понизить общую линию безопасности. Даже администратору вовсе не обязательно иметь прямой доступ к базе данных.

  • Производительность: получение значка SQL «just right» - это искусство, для адмистраторов это не то, что они должны уметь делать правильно. Существует огромный риск того, что люди, которые не являются экспертами, могут создавать огромную нагрузку на базу данных, введя плохой SQL запрос.

Тем не менее, мы можем получить полный авторский доступ, выполнив:

./launcher enter app
rails c
> SiteSetting.enable_badge_sql = true

в командной строке.

SiteSetting.enable_badge_sql = false (по умолчанию). Вам следует вернуть это значение после проведение работ.

Ниже приведены запросы, которые необходимо вставить во вновь появившиеся окно:

Значок для первого принятого ответа:

SELECT p.user_id, p.id post_id, p.updated_at granted_at
FROM badge_posts p
WHERE p.post_number > 1 AND 
    p.id IN (
      SELECT post_id FROM (
       SELECT pc.post_id, row_number() 
       OVER (PARTITION BY p1.user_id ORDER BY pc.created_at) as rnum
       FROM post_custom_fields pc
       JOIN badge_posts p1 ON p1.id = pc.post_id
       JOIN topics t1 ON p1.topic_id = t1.id
       WHERE name = 'is_accepted_answer' AND
                    p1.user_id <> t1.user_id AND 
        (
          :backfill OR 
           p1.user_id IN (
                   select user_id from posts where p1.id IN (:post_ids)
           )
       )
) X  WHERE rnum = 1)

Если вы хотите сделать еще одну награду, то создайте её используя следующий запрос:

Значок для 10 принятых ответов:

SELECT id user_id, current_timestamp granted_at
FROM users
WHERE id  IN (
       SELECT p1.user_id 
       FROM post_custom_fields pc
       JOIN badge_posts p1 ON p1.id = pc.post_id
       JOIN topics t1 ON p1.topic_id = t1.id
       WHERE p1.user_id <> t1.user_id AND 
                    name = 'is_accepted_answer' AND 
                    value IS NOT NULL AND
            p1.user_id IN (
                   SELECT user_id 
                   FROM posts 
                   WHERE :backfill OR  p1.id IN (:post_ids)
            )
        GROUP BY p1.user_id
        HAVING COUNT(*) > 9
)

Посмотрите новые награды в разделе награды, и убедитесь в том, что они присваиваются.

Отдельно необходимо обратить внимание, как вы поставили пересчет (раз в сутки, после обработки сообщения и т.д.). Эти функции находятся на странице добавления награды (сразу под окном с SQL запросом).


(Petrenko) #2

Выдать награду, если пользователь создал хотя бы один вопрос в разделе “comm”

SELECT p.user_id, min(p.created_at) granted_at, MIN(p.id) post_id
FROM badge_posts p
JOIN topics t ON t.id = p.topic_id
WHERE category_id = (
  SELECT id FROM categories WHERE name ilike 'comm'
) AND p.post_number = 1
GROUP BY p.user_id

Выдать награду, если пользователь создал 5 вопросов в разделе “comm”

SELECT p.user_id, min(p.created_at) granted_at, MIN(p.id) post_id
FROM badge_posts p
JOIN topics t ON t.id = p.topic_id
WHERE category_id = (
  SELECT id FROM categories WHERE name ilike 'comm'
) AND p.post_number = 1
GROUP BY p.user_id
HAVING count(*) > 4

Выдать награду, всем участникам группы “comm”

SELECT user_id, created_at granted_at, NULL post_id
FROM group_users
WHERE group_id = (
  SELECT g.id FROM groups g WHERE g.name = 'coom'
)

(Виталий) #3

Кто сделал более 100 сообщений:

SELECT user_id, current_timestamp granted_at 
FROM posts  
GROUP BY user_id 
HAVING count(*) >= 1000

Для посещения 365 дней:

SELECT user_id, current_timestamp granted_at 
FROM user_visits  
GROUP BY user_id 
HAVING count(*) >= 365

Если пользователь включил режим списка рассылки:

SELECT u.id user_id, current_timestamp granted_at
FROM users u
WHERE mailing_list_mode = true
AND (:backfill OR u.id IN (:user_ids))

(Евгений) #4

Отслеживание приглашений

select user_id, invited_by_id
from invites
where created_at > CURRENT_TIMESTAMP - INTERVAL '365 days'
and user_id > 1

Кто следует за тегами

SELECT 
    name, 
    user_id, 
    notification_level 
FROM tag_users tu 
JOIN tags t ON tu.tag_id = t.id


(Андрей Белов) #5

Награды за найденные ошибки. Привязаны к категориям…

Bug Reporter

SELECT distinct p.user_id, p.created_at granted_at, p.id post_id
FROM badge_posts p
JOIN topics t ON t.id = p.topic_id
JOIN post_actions pa ON pa.post_id = p.id AND 
      post_action_type_id = (
                SELECT id FROM post_action_types WHERE name_key = 'like'
       ) AND 
       pa.user_id IN (
           SELECT gu.user_id
           FROM group_users gu
           WHERE gu.group_id = ( SELECT id FROM groups WHERE name ilike 'team' ) 
       )
WHERE category_id = (
  SELECT id FROM categories WHERE name ilike 'bug'
) AND p.post_number = 1

Tech Support

SELECT id user_id, current_timestamp granted_at
FROM users
WHERE id  IN (
       SELECT p1.user_id 
       FROM post_custom_fields pc
       JOIN badge_posts p1 ON p1.id = pc.post_id
       JOIN topics t1 ON p1.topic_id = t1.id
       WHERE p1.user_id <> t1.user_id AND 
                    name = 'is_accepted_answer' AND 
            p1.user_id IN (
                   SELECT user_id 
                   FROM posts 
                   WHERE :backfill OR  p1.id IN (:post_ids)
            )
        GROUP BY p1.user_id
        HAVING COUNT(*) > 9
)

Tester

SELECT p.user_id, MIN(p.created_at) granted_at
  FROM posts p
  JOIN topics t ON t.id = p.topic_id
 WHERE t.category_id = (SELECT id FROM categories WHERE name ILIKE 'bug')
   AND p.post_number = 1
   AND EXISTS (
         SELECT 1
           FROM post_actions pa
          WHERE pa.post_id = p.id 
            AND pa.post_action_type_id = (SELECT id FROM post_action_types WHERE name_key = 'like') 
            AND pa.user_id IN (SELECT user_id FROM group_users WHERE group_id = (SELECT id FROM groups WHERE name ILIKE 'team'))
       )
 GROUP BY p.user_id
HAVING COUNT(*) >= 10

Senior Tester

SELECT p.user_id, MIN(p.created_at) granted_at
  FROM posts p
  JOIN topics t ON t.id = p.topic_id
 WHERE t.category_id = (SELECT id FROM categories WHERE name ILIKE 'bug')
   AND p.post_number = 1
   AND EXISTS (
         SELECT 1
           FROM post_actions pa
          WHERE pa.post_id = p.id 
            AND pa.post_action_type_id = (SELECT id FROM post_action_types WHERE name_key = 'like') 
            AND pa.user_id IN (SELECT user_id FROM group_users WHERE group_id = (SELECT id FROM groups WHERE name ILIKE 'team'))
       )
 GROUP BY p.user_id
HAVING COUNT(*) >= 20

Материал с форума поддержки. Чтобы было все в одном месте.


(Евгений) #6

Вот запрос значка для человека, который отвечает на сообщение в категории (id=1). Post_number > 1 гарантирует, что это ответ, а не первая запись.

SELECT DISTINCT ON (p.user_id)
p.user_id, p.id post_id, p.created_at granted_at
FROM badge_posts p
JOIN topics t ON t.id = p.topic_id
WHERE category_id = 1 AND p.post_number > 1
AND (:backfill OR p.id IN (:post_ids) )