Coverage for polar/benefit/strategies/discord/schemas.py: 85%

41 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-12-05 16:17 +0000

1from typing import Literal 1a

2 

3from pydantic import Field, computed_field, field_validator 1a

4 

5from polar.config import settings 1a

6from polar.kit import jwt 1a

7from polar.kit.schemas import Schema 1a

8from polar.models.benefit import BenefitType 1a

9 

10from ..base.schemas import ( 1a

11 BenefitBase, 

12 BenefitCreateBase, 

13 BenefitSubscriberBase, 

14 BenefitUpdateBase, 

15) 

16 

17 

18class BenefitDiscordProperties(Schema): 1a

19 """ 

20 Properties for a benefit of type `discord`. 

21 """ 

22 

23 guild_id: str = Field(..., description="The ID of the Discord server.") 1a

24 role_id: str = Field(..., description="The ID of the Discord role to grant.") 1a

25 kick_member: bool = Field( 1a

26 ..., 

27 description="Whether to kick the member from the Discord server on revocation.", 

28 ) 

29 

30 @computed_field # type: ignore[prop-decorator] 1a

31 @property 1a

32 def guild_token(self) -> str: 1a

33 return jwt.encode( 

34 data={"guild_id": self.guild_id}, 

35 secret=settings.SECRET, 

36 type="discord_guild_token", 

37 ) 

38 

39 

40class BenefitDiscordCreateProperties(Schema): 1a

41 """ 

42 Properties to create a benefit of type `discord`. 

43 """ 

44 

45 guild_token: str = Field(serialization_alias="guild_id") 1a

46 role_id: str = Field(..., description="The ID of the Discord role to grant.") 1a

47 kick_member: bool = Field( 1a

48 ..., 

49 description="Whether to kick the member from the Discord server on revocation.", 

50 ) 

51 

52 @field_validator("guild_token") 1a

53 @classmethod 1a

54 def validate_guild_token(cls, v: str) -> str: 1a

55 try: 

56 guild_token_data = jwt.decode( 

57 token=v, secret=settings.SECRET, type="discord_guild_token" 

58 ) 

59 return guild_token_data["guild_id"] 

60 except (KeyError, jwt.DecodeError, jwt.ExpiredSignatureError) as e: 

61 raise ValueError( 

62 "Invalid token. Please authenticate your Discord server again." 

63 ) from e 

64 

65 

66class BenefitDiscordSubscriberProperties(Schema): 1a

67 """ 

68 Properties available to subscribers for a benefit of type `discord`. 

69 """ 

70 

71 guild_id: str = Field(..., description="The ID of the Discord server.") 1a

72 

73 

74class BenefitDiscordCreate(BenefitCreateBase): 1a

75 type: Literal[BenefitType.discord] 1a

76 properties: BenefitDiscordCreateProperties 1a

77 

78 

79class BenefitDiscordUpdate(BenefitUpdateBase): 1a

80 type: Literal[BenefitType.discord] 1a

81 properties: BenefitDiscordCreateProperties | None = None 1a

82 

83 

84class BenefitDiscord(BenefitBase): 1a

85 """ 

86 A benefit of type `discord`. 

87 

88 Use it to automatically invite your backers to a Discord server. 

89 """ 

90 

91 type: Literal[BenefitType.discord] 1a

92 properties: BenefitDiscordProperties 1a

93 

94 

95class BenefitDiscordSubscriber(BenefitSubscriberBase): 1a

96 type: Literal[BenefitType.discord] 1a

97 properties: BenefitDiscordSubscriberProperties 1a