Skip to content

Commit bb3ecdb

Browse files
authored
Merge pull request #1 from dojoengine/kronosapiens/team-role-decay
feat: exempt team role from sensei decay
2 parents 71c8a76 + 4f458dd commit bb3ecdb

6 files changed

Lines changed: 31 additions & 2 deletions

File tree

backend/.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ KOHAI_ROLE_ID=your_kohai_role_id
1212
SENPAI_ROLE_ID=your_senpai_role_id
1313
SENSEI_ROLE_ID=your_sensei_role_id
1414
FELT_ROLE_ID=your_felt_role_id
15+
TEAM_ROLE_ID=your_team_role_id
1516

1617
# Database (PostgreSQL connection string)
1718
DATABASE_URL=postgres://user:password@localhost:5432/daimyo

backend/.env.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ KOHAI_ROLE_ID=kohai-role-id
1010
SENPAI_ROLE_ID=senpai-role-id
1111
SENSEI_ROLE_ID=sensei-role-id
1212
FELT_ROLE_ID=felt-role-id
13+
TEAM_ROLE_ID=team-role-id
1314

1415
DATABASE_PATH=:memory:
1516

backend/__tests__/unit/decay.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ jest.unstable_mockModule('../../src/utils/config.js', () => ({
3131
decayWindowDays: 360,
3232
senseiReactionThreshold: 30,
3333
feltRoleId: 'felt-role-id',
34+
teamRoleId: 'team-role-id',
3435
},
3536
}));
3637

@@ -183,6 +184,26 @@ describe('Decay Service', () => {
183184
expect(mockInsertRoleHistory).not.toHaveBeenCalled();
184185
expect(mockGetRecentSenseiReactions).not.toHaveBeenCalled();
185186
});
187+
188+
test('should not demote Sensei with Team role (core team exempt)', async () => {
189+
const guild = createMockGuild();
190+
const member = createMockMember('user-1', 'TestUser#0001', [
191+
'sensei-role-id',
192+
'team-role-id',
193+
]);
194+
guild.members.cache.set('user-1', member);
195+
196+
mockGetUserRole.mockReturnValue(Role.Sensei);
197+
// No reactions at all - would normally trigger demotion
198+
mockGetRecentSenseiReactions.mockResolvedValue([]);
199+
200+
const result = await checkSenseiDecay(guild as any, 'user-1');
201+
202+
expect(result.demoted).toBe(false);
203+
expect(mockAssignRole).not.toHaveBeenCalled();
204+
expect(mockInsertRoleHistory).not.toHaveBeenCalled();
205+
expect(mockGetRecentSenseiReactions).not.toHaveBeenCalled();
206+
});
186207
});
187208

188209
describe('getSenseiDecayStatus', () => {

backend/src/services/decay.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { getUserRole, assignRole, sendDM, formatDemotionMessage } from './roleMa
77
/**
88
* Check if a Sensei should be demoted due to insufficient recent reactions
99
* Sensei must maintain 30+ Sensei reactions within the last 360 days
10-
* Sensei with Felt role are exempt from decay (core group)
10+
* Sensei with Felt or Team role are exempt from decay (core group)
1111
*/
1212
export async function checkSenseiDecay(guild: Guild, userId: string): Promise<DemotionResult> {
1313
try {
@@ -18,12 +18,16 @@ export async function checkSenseiDecay(guild: Guild, userId: string): Promise<De
1818
return { demoted: false };
1919
}
2020

21-
// Sensei with Felt role are exempt from decay (core group)
21+
// Sensei with Felt or Team role are exempt from decay (core group)
2222
const member = guild.members.cache.get(userId);
2323
if (member && config.feltRoleId && member.roles.cache.has(config.feltRoleId)) {
2424
console.debug(`Skipping decay check for ${userId}: has Felt role (core group)`);
2525
return { demoted: false };
2626
}
27+
if (member && config.teamRoleId && member.roles.cache.has(config.teamRoleId)) {
28+
console.debug(`Skipping decay check for ${userId}: has Team role (core group)`);
29+
return { demoted: false };
30+
}
2731

2832
// Get Sensei reactions within the decay window
2933
const recentReactions = await getRecentSenseiReactions(userId, config.decayWindowDays);

backend/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export interface Config {
5252
senpaiRoleId: string;
5353
senseiRoleId: string;
5454
feltRoleId: string;
55+
teamRoleId: string;
5556

5657
// Channel IDs
5758
ohayoChannelId: string;

backend/src/utils/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export function loadConfig(): Config {
5656
senpaiRoleId: getRequiredEnv('SENPAI_ROLE_ID'),
5757
senseiRoleId: getRequiredEnv('SENSEI_ROLE_ID'),
5858
feltRoleId: getRequiredEnv('FELT_ROLE_ID'),
59+
teamRoleId: getRequiredEnv('TEAM_ROLE_ID'),
5960

6061
// Channel IDs
6162
ohayoChannelId: getRequiredEnv('OHAYO_CHANNEL_ID'),

0 commit comments

Comments
 (0)