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

110 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-09-10 04:45 +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/avatars are publicly downloadable URLs, " 

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

103 "leak client IPs 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 

147NO_UPLOAD_MAX_DAYS: int | None = None 

148NO_UPLOAD_MAX_DAYS__DOC = ( 

149 "Expire attachments after X days. If unset, MAM_MAX_DAYS is used." 

150) 

151NO_UPLOAD_MAX_DAYS__CATEGORY = _Categories.ATTACHMENTS 

152 

153 

154IGNORE_DELAY_THRESHOLD = 300 

155IGNORE_DELAY_THRESHOLD__DOC = ( 

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

157 "out of emitted stanzas." 

158) 

159IGNORE_DELAY_THRESHOLD__CATEGORY = _Categories.ADVANCED 

160 

161PARTIAL_REGISTRATION_TIMEOUT = 3600 

162PARTIAL_REGISTRATION_TIMEOUT__DOC = ( 

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

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

165) 

166PARTIAL_REGISTRATION_TIMEOUT__CATEGORY = _Categories.ADVANCED 

167 

168QR_TIMEOUT = 60 

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

170QR_TIMEOUT__CATEGORY = _Categories.ADVANCED 

171 

172FIX_FILENAME_SUFFIX_MIME_TYPE: bool = False 

173FIX_FILENAME_SUFFIX_MIME_TYPE__DOC = ( 

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

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

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

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

178) 

179FIX_FILENAME_SUFFIX_MIME_TYPE__CATEGORY = _Categories.ATTACHMENTS 

180 

181LOG_FILE: Path | None = None 

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

183LOG_FILE__CATEGORY = _Categories.LOG 

184 

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

186LOG_FORMAT__DOC = ( 

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

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

189 "for available options." 

190) 

191LOG_FORMAT__CATEGORY = _Categories.LOG 

192 

193MAM_MAX_DAYS = 7 

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

195MAM_MAX_DAYS__CATEGORY = _Categories.BASE 

196 

197ATTACHMENT_MAXIMUM_FILE_NAME_LENGTH = 200 

198ATTACHMENT_MAXIMUM_FILE_NAME_LENGTH__DOC = ( 

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

200 "preserving suffix." 

201) 

202ATTACHMENT_MAXIMUM_FILE_NAME_LENGTH__CATEGORY = _Categories.ATTACHMENTS 

203 

204CONVERT_STICKERS: bool = False 

205CONVERT_STICKERS__DOC = ( 

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

207) 

208CONVERT_STICKERS__CATEGORY = _Categories.ATTACHMENTS 

209 

210AVATAR_RESAMPLING_THREADS = 2 

211AVATAR_RESAMPLING_THREADS__DOC = ( 

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

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

214) 

215AVATAR_RESAMPLING_THREADS__CATEGORY = _Categories.ADVANCED 

216 

217DEV_MODE = False 

218DEV_MODE__DOC = ( 

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

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

221) 

222DEV_MODE__CATEGORY = _Categories.ADVANCED 

223 

224 

225STRIP_LEADING_EMOJI_ADHOC = False 

226STRIP_LEADING_EMOJI_ADHOC__DOC = ( 

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

228 "are a emoji-hater." 

229) 

230STRIP_LEADING_EMOJI_ADHOC__CATEGORY = _Categories.ADVANCED 

231 

232COMPONENT_NAME: str | None = None 

233COMPONENT_NAME__DOC = ( 

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

235 "of the component in chat windows." 

236) 

237COMPONENT_NAME__CATEGORY = _Categories.ADVANCED 

238 

239WELCOME_MESSAGE: str | None = None 

240WELCOME_MESSAGE__DOC = ( 

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

242) 

243WELCOME_MESSAGE__CATEGORY = _Categories.ADVANCED