Coverage for slidge/core/config.py: 100%

107 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-08-18 04:30 +0000

1from pathlib import Path 

2 

3from slixmpp import JID as JIDType 

4 

5# REQUIRED, so not default value 

6 

7 

8class _Categories: 

9 MANDATORY = (0, "Mandatory settings") 

10 BASE = (10, "Basic configuration") 

11 ATTACHMENTS = (20, "Attachments") 

12 LOG = (30, "Logging") 

13 ADVANCED = (40, "Advanced settings") 

14 

15 

16LEGACY_MODULE: str 

17LEGACY_MODULE__DOC = ( 

18 "Importable python module containing (at least) a BaseGateway and a LegacySession subclass. " 

19 "NB: this is not needed if you use a gateway-specific entrypoint, e.g., `slidgram` or " 

20 "`python -m slidgram`." 

21) 

22LEGACY_MODULE__CATEGORY = _Categories.BASE 

23 

24SERVER: str = "localhost" 

25SERVER__DOC = ( 

26 "The XMPP server's host name. Defaults to localhost, which is the " 

27 "standard way of running slidge, on the same host as the XMPP server. " 

28 "The 'Jabber Component Protocol' (XEP-0114) does not mention encryption, " 

29 "so you *should* provide encryption another way, eg via port forwarding, if " 

30 "you change this." 

31) 

32SERVER__SHORT = "s" 

33SERVER__CATEGORY = _Categories.BASE 

34 

35SECRET: str 

36SECRET__DOC = "The gateway component's secret (required to connect to the XMPP server)" 

37SECRET__CATEGORY = _Categories.MANDATORY 

38 

39JID: JIDType 

40JID__DOC = "The gateway component's JID" 

41JID__SHORT = "j" 

42JID__CATEGORY = _Categories.MANDATORY 

43 

44PORT: str = "5347" 

45PORT__DOC = "The XMPP server's port for incoming component connections" 

46PORT__SHORT = "p" 

47PORT__CATEGORY = _Categories.BASE 

48 

49# Dynamic default (depends on other values) 

50 

51HOME_DIR: Path 

52HOME_DIR__DOC = ( 

53 "Directory where slidge will writes it persistent data and cache. " 

54 "Defaults to /var/lib/slidge/${SLIDGE_JID}. " 

55) 

56HOME_DIR__DYNAMIC_DEFAULT = True 

57HOME_DIR__CATEGORY = _Categories.BASE 

58 

59DB_URL: str 

60DB_URL__DOC = ( 

61 "Database URL, see <https://docs.sqlalchemy.org/en/20/core/engines.html#database-urls>. " 

62 "Defaults to `sqlite:///${HOME_DIR}/slidge.sqlite`. " 

63 "SQLite is *highly recommended*, other backends such as postgresql may work by chance but " 

64 "are much less tested." 

65) 

66DB_URL__DYNAMIC_DEFAULT = True 

67DB_URL__CATEGORY = _Categories.ADVANCED 

68 

69USER_JID_VALIDATOR: str 

70USER_JID_VALIDATOR__DOC = ( 

71 "Regular expression to restrict users that can register to the gateway, by JID. " 

72 "Defaults to .*@${INFERRED_SERVER}. INFERRED_SERVER is derived for the gateway JID, " 

73 "by removing whatever is before the first encountered dot in it. Example: if " 

74 "slidge's JID=slidge.example.org, INFERRED_SERVER=example.org." 

75) 

76USER_JID_VALIDATOR__DYNAMIC_DEFAULT = True 

77USER_JID_VALIDATOR__CATEGORY = _Categories.BASE 

78 

79# Optional, so default value + type hint if default is None 

80 

81ADMINS: tuple[JIDType, ...] = () 

82ADMINS__DOC = "JIDs of the gateway admins" 

83ADMINS__CATEGORY = _Categories.BASE 

84 

85UPLOAD_SERVICE: str | None = None 

86UPLOAD_SERVICE__DOC = ( 

87 "JID of an HTTP upload service the gateway can use. " 

88 "This is optional, as it should be automatically determined via service" 

89 "discovery." 

90) 

91UPLOAD_SERVICE__CATEGORY = _Categories.ATTACHMENTS 

92 

93AVATAR_SIZE = 200 

94AVATAR_SIZE__DOC = ( 

95 "Maximum image size (width and height), image ratio will be preserved" 

96) 

97AVATAR_SIZE__CATEGORY = _Categories.ADVANCED 

98 

99USE_ATTACHMENT_ORIGINAL_URLS: bool = False 

100USE_ATTACHMENT_ORIGINAL_URLS__DOC = ( 

101 "For legacy plugins in which attachments are publicly downloadable URLs, " 

102 "let XMPP clients directly download them from this URL. Note that this will " 

103 "probably leak your client IP to the legacy network." 

104) 

105USE_ATTACHMENT_ORIGINAL_URLS__CATEGORY = _Categories.ATTACHMENTS 

106 

107UPLOAD_REQUESTER: str | None = None 

108UPLOAD_REQUESTER__DOC = ( 

109 "Set which JID should request the upload slots. Defaults to the user's JID if " 

110 "IQ/get privileges granted for the 'urn:xmpp:http:upload:0' namespace; the component " 

111 "JID otherwise." 

112) 

113UPLOAD_REQUESTER__CATEGORY = _Categories.ATTACHMENTS 

114 

115UPLOAD_URL_PREFIX: str | None = None 

116UPLOAD_URL_PREFIX__DOC = ( 

117 "This is an optional setting to make sure the URL of your upload service is never leaked " 

118 "to the legacy network in bodies of messages. This can happen under rare circumstances and/or bugs," 

119 "when replying to an attachment. Set this to the common prefix of the public URL your attachments get, " 

120 "eg https://upload.example.org:5281/" 

121) 

122UPLOAD_URL_PREFIX__CATEGORY = _Categories.ATTACHMENTS 

123 

124NO_UPLOAD_PATH: str | None = None 

125NO_UPLOAD_PATH__DOC = ( 

126 "Instead of using the XMPP server's HTTP upload component, copy files to this dir. " 

127 "You need to set NO_UPLOAD_URL_PREFIX too if you use this option, and configure " 

128 "an web server to serve files in this dir." 

129) 

130NO_UPLOAD_PATH__CATEGORY = _Categories.ATTACHMENTS 

131 

132NO_UPLOAD_URL_PREFIX: str | None = None 

133NO_UPLOAD_URL_PREFIX__DOC = ( 

134 "Base URL that servers files in the dir set in the no-upload-path option, " 

135 "eg https://example.com:666/slidge-attachments/" 

136) 

137NO_UPLOAD_URL_PREFIX__CATEGORY = _Categories.ATTACHMENTS 

138 

139 

140NO_UPLOAD_FILE_READ_OTHERS: bool = False 

141NO_UPLOAD_FILE_READ_OTHERS__DOC = ( 

142 "After writing a file in NO_UPLOAD_PATH, change its permission so that 'others' can" 

143 " read it." 

144) 

145NO_UPLOAD_FILE_READ_OTHERS__CATEGORY = _Categories.ATTACHMENTS 

146 

147IGNORE_DELAY_THRESHOLD = 300 

148IGNORE_DELAY_THRESHOLD__DOC = ( 

149 "Threshold, in seconds, below which the <delay> information is stripped " 

150 "out of emitted stanzas." 

151) 

152IGNORE_DELAY_THRESHOLD__CATEGORY = _Categories.ADVANCED 

153 

154PARTIAL_REGISTRATION_TIMEOUT = 3600 

155PARTIAL_REGISTRATION_TIMEOUT__DOC = ( 

156 "Timeout before registration and login. Only useful for legacy networks where " 

157 "a single step registration process is not enough." 

158) 

159PARTIAL_REGISTRATION_TIMEOUT__CATEGORY = _Categories.ADVANCED 

160 

161QR_TIMEOUT = 60 

162QR_TIMEOUT__DOC = "Timeout for QR code flashing confirmation." 

163QR_TIMEOUT__CATEGORY = _Categories.ADVANCED 

164 

165FIX_FILENAME_SUFFIX_MIME_TYPE: bool = False 

166FIX_FILENAME_SUFFIX_MIME_TYPE__DOC = ( 

167 "Fix the Filename suffix based on the Mime Type of the file. Some clients (eg" 

168 " Conversations) may not inline files that have a wrong suffix for the MIME Type." 

169 " Therefore the MIME Type of the file is checked, if the suffix is not valid for" 

170 " that MIME Type, a valid one will be picked." 

171) 

172FIX_FILENAME_SUFFIX_MIME_TYPE__CATEGORY = _Categories.ATTACHMENTS 

173 

174LOG_FILE: Path | None = None 

175LOG_FILE__DOC = "Log to a file instead of stdout/err" 

176LOG_FILE__CATEGORY = _Categories.LOG 

177 

178LOG_FORMAT: str = "%(levelname)s:%(name)s:%(message)s" 

179LOG_FORMAT__DOC = ( 

180 "Optionally, a format string for logging messages. Refer to " 

181 "https://docs.python.org/3/library/logging.html#logrecord-attributes " 

182 "for available options." 

183) 

184LOG_FORMAT__CATEGORY = _Categories.LOG 

185 

186MAM_MAX_DAYS = 7 

187MAM_MAX_DAYS__DOC = "Maximum number of days for group archive retention." 

188MAM_MAX_DAYS__CATEGORY = _Categories.BASE 

189 

190ATTACHMENT_MAXIMUM_FILE_NAME_LENGTH = 200 

191ATTACHMENT_MAXIMUM_FILE_NAME_LENGTH__DOC = ( 

192 "Some legacy network provide ridiculously long filenames, strip above this limit, " 

193 "preserving suffix." 

194) 

195ATTACHMENT_MAXIMUM_FILE_NAME_LENGTH__CATEGORY = _Categories.ATTACHMENTS 

196 

197CONVERT_STICKERS: bool = False 

198CONVERT_STICKERS__DOC = ( 

199 "Convert lottie vector stickers (from the legacy side) to webp animations." 

200) 

201CONVERT_STICKERS__CATEGORY = _Categories.ATTACHMENTS 

202 

203AVATAR_RESAMPLING_THREADS = 2 

204AVATAR_RESAMPLING_THREADS__DOC = ( 

205 "Number of additional threads to use for avatar resampling. Even in a single-core " 

206 "context, this makes avatar resampling non-blocking." 

207) 

208AVATAR_RESAMPLING_THREADS__CATEGORY = _Categories.ADVANCED 

209 

210DEV_MODE = False 

211DEV_MODE__DOC = ( 

212 "Enables an interactive python shell via chat commands, for admins." 

213 "Not safe to use in prod, but great during dev." 

214) 

215DEV_MODE__CATEGORY = _Categories.ADVANCED 

216 

217 

218STRIP_LEADING_EMOJI_ADHOC = False 

219STRIP_LEADING_EMOJI_ADHOC__DOC = ( 

220 "Strip the leading emoji in ad-hoc command names, if present, in case you " 

221 "are a emoji-hater." 

222) 

223STRIP_LEADING_EMOJI_ADHOC__CATEGORY = _Categories.ADVANCED 

224 

225COMPONENT_NAME: str | None = None 

226COMPONENT_NAME__DOC = ( 

227 "Overrides the default component name with a custom one. This is seen in service discovery and as the nickname " 

228 "of the component in chat windows." 

229) 

230COMPONENT_NAME__CATEGORY = _Categories.ADVANCED 

231 

232WELCOME_MESSAGE: str | None = None 

233WELCOME_MESSAGE__DOC = ( 

234 "Overrides the default welcome message received by newly registered users." 

235) 

236WELCOME_MESSAGE__CATEGORY = _Categories.ADVANCED