Skip to content

Commit 0e241be

Browse files
committed
Skip missing Discord language roles at server limit
1 parent 171bc29 commit 0e241be

2 files changed

Lines changed: 44 additions & 3 deletions

File tree

lib/polish_open_source_rank/contexts/community/infrastructure/discord/discord_role_map.rb

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def role_ids(keys)
2727
:channels,
2828
:category_id,
2929
:channel_creation_disabled,
30+
:role_creation_disabled,
3031
keyword_init: true
3132
)
3233

@@ -95,7 +96,8 @@ def provisioning_state
9596
roles: gateway.guild_roles,
9697
channels: channels,
9798
category_id: ensure_category_id(channels),
98-
channel_creation_disabled: false
99+
channel_creation_disabled: false,
100+
role_creation_disabled: false
99101
)
100102
end
101103

@@ -117,7 +119,9 @@ def ensure_language_resources(role_keys, state)
117119
end
118120

119121
def ensure_language_role_and_channel(role_key, state)
120-
role = ensure_dynamic_role(role_key, state.roles)
122+
role = ensure_dynamic_role(role_key, state)
123+
return unless role
124+
121125
ensure_dynamic_channel(role_key, role.fetch('id'), state)
122126
end
123127

@@ -133,14 +137,22 @@ def ensure_category_id(channels)
133137
category.fetch('id')
134138
end
135139

136-
def ensure_dynamic_role(role_key, roles)
140+
def ensure_dynamic_role(role_key, state)
141+
return if state.role_creation_disabled
142+
143+
roles = state.roles
137144
role_name = role_catalog.role_name(role_key)
138145
role = roles.find { |candidate| candidate.fetch('name') == role_name }
139146
return role if role
140147

141148
role = gateway.create_role(name: role_name, color: Domain::DiscordLanguageRoleKey.new(role_key).role_color)
142149
roles << role
143150
role
151+
rescue DiscordApiGateway::Error => e
152+
raise unless server_role_limit?(e)
153+
154+
state.role_creation_disabled = true
155+
nil
144156
end
145157

146158
def ensure_dynamic_channel(role_key, role_id, state)
@@ -181,6 +193,10 @@ def language_role_keys(languages)
181193
def category_channel_limit?(error)
182194
error.message.include?('CHANNEL_PARENT_MAX_CHANNELS')
183195
end
196+
197+
def server_role_limit?(error)
198+
error.message.include?('"code": 30005') || error.message.include?('Maximum number of server roles')
199+
end
184200
end
185201
end
186202
end

spec/polish_open_source_rank/contexts/community/infrastructure/discord/discord_role_map_spec.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,31 @@
149149
end
150150
end
151151

152+
context 'when Discord refuses another dynamic role because the server role limit is reached' do
153+
before do
154+
allow(gateway).to receive(:create_role)
155+
.with(name: 'Ruby', color: nil)
156+
.and_raise(
157+
PolishOpenSourceRank::Contexts::Community::Infrastructure::Discord::DiscordApiGateway::Error,
158+
'400 {"message":"Maximum number of server roles reached (250)","code":30005}'
159+
)
160+
end
161+
162+
it 'keeps static roles available and omits missing dynamic roles' do
163+
ENV['DISCORD_ROLE_TOP_100_PL'] = 'country-role'
164+
165+
prepared = map.prepare(
166+
period_start: '2026-04-01',
167+
role_keys: ['DISCORD_ROLE_TOP_100_PL', 'DISCORD_ROLE_LANGUAGE:ruby:Ruby']
168+
)
169+
170+
expect(prepared.managed_role_ids).to include('country-role')
171+
expect(prepared.role_ids_by_key).to be_empty
172+
expect(gateway_data.fetch(:created_roles)).to be_empty
173+
expect(gateway_data.fetch(:created_channels).map { |channel| channel.fetch('name') }).to eq(['Languages'])
174+
end
175+
end
176+
152177
def discord_gateway_contract
153178
Object.new.tap do |gateway|
154179
def gateway.guild_roles; end

0 commit comments

Comments
 (0)