면책 조항: 네, 이 문제를 수정하는 데 Claude를 사용했습니다:
Discourse 코어 커밋 5ee8e24 (2026-08-19)를 실행 중입니다. Patreon 동기화는 오류 없이 완료되지만 동기화된 사용자가 0명입니다:
Patreon sync complete: 63 pledges, 0 users synced
API 응답은 모두 status=200이므로 요청 자체에는 문제가 없습니다. Rails 콘솔에서 추적해 보니 플러그인이 구성하는 멤버 요청은 정확하며, member 리소스에서 이메일을 요청하고 있습니다:
fields[member]=full_name,last_charge_date,last_charge_status,currently_entitled_amount_cents,patron_status,email
적절하게 스코프된 크리에이터 토큰(campaigns.members[email] 권한 부여)으로 해당 엔드포인트를 직접 호출하면, 이메일은 included의 user 객체가 아니라 member 객체에 존재합니다. 단일 멤버 조회를 통해 이를 확인했습니다:
data.attributes.email => "patron@example.com" # 존재
included[].attributes.email => (없음) # user 객체는 full_name만 포함
따라서 캠페인 멤버 목록에서 member.attributes.email은 값이 채워져 있습니다(제 63명의 멤버 중 46명; 나머지는 공유 제한이 있거나 무료 팔로워입니다). 반면 included의 user 항목에는 이메일 필드가 전혀 없습니다.
문제는 Patreon::ApiVersion::V2.extract (lib/api_version/v2.rb)에 있습니다. included user 객체로부터 users 맵을 구성합니다:
ruby
(member_data["included"] || []).each do |entry|
if entry["type"] == "user" && entry["attributes"]["email"].present?
users[entry["id"]] = entry["attributes"]["email"].downcase
end
end
해당 user 객체에는 이메일이 없으므로 맵은 비어 있게 되고, 모든 멤버가 이메일 매칭에 실패하여 동기화된 사용자가 0명이 됩니다.
included 대신 member 항목에서 이메일을 읽으면(이미 member.relationships.user.data.id에 사용 가능한 user id를 키로 사용하여, pledge에 사용되는 patron_id와 동일합니다) 제 설치 환경에서 문제가 해결되었습니다: 0이 46 users synced로 바뀌었습니다. 제가 적용한 변경 사항:
diff
+ users[patron_id] = attrs["email"].downcase if attrs["email"].present?
pledges[patron_id] = attrs["currently_entitled_amount_cents"]
declines[patron_id] = attrs["last_charge_date"] if attrs["last_charge_status"] == "Declined"
end
-
- (member_data["included"] || []).each do |entry|
- if entry["type"] == "user" && entry["attributes"]["email"].present?
- users[entry["id"]] = entry["attributes"]["email"].downcase
- end
- end
included 루프를 완전히 제거하는 것이 모든 경우에 올바른 결정인지 확신이 서지 않습니다 — 일부 설정에서는 user 객체에 이메일이 수신될 수 있으므로, 대체하는 대신 폴백으로 유지하는 것이 좋을 수도 있습니다. 관찰된 동작과 여기서 작동한 최소한의 변경 사항을 게시하여 유용하거나 올바른 수정 방향을 제시하는 데 도움이 되길 바랍니다.