Patreon não parece estar sincronizando em nossa instância

Estamos em uma instância hospedada no discourse.group. Configuramos o plug-in do Patreon para atualizar um grupo chamado Patrons (Padrinhos), e qualquer pessoa de qualquer nível deve ser incluída nesse grupo. No momento, apesar de mais de 1000 padrinhos ativos no Patreon, este grupo tem apenas cerca de 70 membros, o que parece ser muito pequeno, especialmente considerando que, exceto por algumas pessoas que receberam convites diretos, só apoiamos pessoas que fazem login com o Patreon.

Faz dois dias desde que a sincronização foi executada de acordo com o painel do plug-in na administração, contrariando a documentação que sugere que ela deve ser executada a cada 6 horas, e essa última execução coincidiu com várias pessoas sendo removidas deste grupo e uma falha no log (que parece ser uma resposta do CloudFlare e não do api.patreon.com em si). Vemos falhas semelhantes em intervalos de aproximadamente duas semanas.

Clicar no botão “Update Patreon Data & Sync Groups” (Atualizar Dados do Patreon e Sincronizar Grupos) no painel de administração do plug-in parece não fazer nada (temos o registro detalhado ativado para o plug-in, e nada é registrado).

Eu pessoalmente não tenho acesso de administrador à conta do Patreon à qual estamos vinculados, mas se eu usar o token de criador configurado para o plug-in contra os endpoints da API (com curl), funciona e consigo obter respostas válidas, navegar pelas assinaturas, etc. Houve um tópico anterior que sugeria que os limites de solicitação para essa instância precisavam ser aumentados; eu fiz isso na nossa instância, mas parece não ter tido efeito.

Procurei alguns tópicos relevantes:

Mas pelo que posso ver, parece que a sincronização não está ocorrendo nem manualmente nem em um cronograma, ou pelo menos não no cronograma 4 vezes ao dia que a documentação implica, e como não estamos auto-hospedados, acho que estou no limite do que posso inspecionar por conta própria.

Oi,

Acho que posso ter encontrado a causa deste problema, ou pelo menos um problema de sincronização da API v2 do Patreon intimamente relacionado.

Tenho uma instância do Discourse usando a integração com o Patreon com a API v2. Os usuários existentes do Patreon continuam sendo atribuídos corretamente ao grupo patrons, mas um novo membro pagante não foi adicionado ao grupo, mesmo após executar manualmente Atualizar dados do Patreon. A sincronização foi concluída com sucesso e o endereço de e-mail no Patreon correspondia exatamente ao e-mail do usuário no Discourse.

Com patreon_verbose_log habilitado, a sincronização relata:

Patreon sync: found 4 rewards/tiers across 1 campaigns
Patreon sync complete: 1968 pledges, 0 users synced

Em seguida, inspecionei a resposta da API usada por ApiVersion::V2.

Para a primeira página com 1.000 membros:

Members in data: 1000
Included total: 1004
Included users: 1000
Keys for first included user: ["full_name"]
Included users with email: 0

No entanto, os próprios objetos member contêm o e-mail:

Members: 1000
Keys for first member:
["currently_entitled_amount_cents", "email", "full_name",
 "last_charge_date", "last_charge_status", "patron_status"]

Members with email: 928

Olhando para plugins/discourse-patreon/lib/api_version/v2.rb, MEMBER_FIELDS solicita explicitamente email, mas V2.extract apenas preenche o hash users a partir dos objetos user relacionados em included:

(member_data["included"] || []).each do |entry|
  if entry["type"] == "user" && entry["attributes"]["email"].present?
    users[entry["id"]] = entry["attributes"]["email"].downcase
  end
end

Parece que ele não usa entry["attributes"]["email"] dos objetos member, mesmo que seja esse o local onde o Patreon está retornando o e-mail na minha resposta da API.

Isso parece explicar por que a sincronização recupera com sucesso todas as 1.968 assinaturas, mas relata 0 users synced.

Também explica por que as associações existentes entre Patreon/Discourse podem continuar funcionando, enquanto novos membros não podem ser correspondidos por e-mail: os usuários existentes podem já ter seu patreon_id armazenado em user_custom_fields, enquanto um novo membro precisa que a associação entre ID do Patreon ↔ e-mail seja estabelecida.

Faria sentido que V2.extract preenchesse users diretamente ao processar cada membro, por exemplo:

patron_id = entry["relationships"]["user"]["data"]["id"]
attrs = entry["attributes"]

if attrs["email"].present?
  users[patron_id] = attrs["email"].downcase
end

mantendo o processamento atual de included como um fallback?