To refresh a token, when it expires, you won’t need a web inbound accessable server. And you’ll only need to refresh at boot. Just if the refresh fails you won’t be able to auto fetch a new token. Which is the same for if the token is revoked. You can even set this first token up using localhost as the redirect (and still not need a web server)
So you’ll only have to paint the bot with an initial access token/refresh token, and then it should look after itself.
You only have to suck it up to paint the bot once.