myflaskserver is a Flask-based personal gateway service. Some useful modules are designed in wecom_responder/routes. It is mainly used as a endpoint for responding my WeCom bot messages, with some other features like a small DDNS-style redirect dashboard, and exposing webhook endpoints for FreshrssCrawler. Also include two WeCom bots: TVSubscriberBot for subscribing TV programs and DrinkBot for recording daily drink intake. Both bots support interactive queries and scheduled tasks, and are bridged to WeCom through the subscribe channel and drink channel modules respectively.
At startup, BpLoader scans wecom_responder/routes/*/*.py, imports modules
whose filename matches the route directory name, and registers every Flask
Blueprint object found in that module if enabled_modules.<module_name> is
true in config.json.
For example, routes/webhook/webhook.py is imported as
wecom_responder.routes.webhook.webhook.
The subscribe_chan module bridges incoming WeCom messages to a local text bot TVSubscriberBot in subbot.py
and sends bot results back to WeCom. The TVSubscriberBot queries and subscribe tv programs. It interactively ask for tv information like channel name and program title, and supports scheduled queries.
It creates a WecomReceiver with URL prefix:
/subscribe_chan_recv
WecomReceiver itself registers the callback endpoints used by WeCom for URL
verification and message delivery.
Sends a processed text result back to a WeCom user.
Expected JSON body:
{
"result": "message text"
}Behavior:
- Reads
resultfrom the JSON body. - Sends it to
touidthroughWecomSan.send_autosplit. - Splits content according to
MAX_RESPONSE_BYTES. - Returns
OKwhen a non-empty result is submitted.
Incoming text messages received by /subscribe_chan_recv are converted into
local User/Chat objects and submitted to TextSubmitter at
DUMBBOT_HOST:SUBBOT_PORT.
The drink_chan module has the same bridge pattern as subscribe_chan, using
the drink bot port instead. The bot defined in drinkbot.py records daily drink intake and provides statistics like weekly/monthly intake charts. It also supports interactive queries and scheduled reminders.
It creates a WecomReceiver with URL prefix:
/drink_chan_recv
Incoming text messages are submitted to TextSubmitter at
DUMBBOT_HOST:DRINKBOT_PORT.
Sends a processed text result back to a WeCom user.
Expected JSON body:
{
"result": "message text"
}Behavior:
- Reads
resultfrom the JSON body. - Sends it to
touidthroughWecomSan.send_autosplit. - Splits content according to
MAX_RESPONSE_BYTES. - Returns
OKwhen a non-empty result is submitted.
Sends an image result back to a WeCom user.
Expected JSON body:
{
"result": "image media id or image payload accepted by WecomSan"
}Behavior:
- Reads
resultfrom the JSON body. - Sends it to
touidthroughWecomSan.send_image. - Returns
OKwhen a non-empty result is submitted.
Receives a FreshRSS-style JSON payload and forwards it to a WeCom bot (FreshrssCrawler) as a text-card message. Used for periodically sending RSS feed updates collected by my FreshRSS service to WeCom.
Expected fields used by the implementation:
{
"title": "item title",
"feed": "feed title",
"url": "original item URL",
"created": "timestamp",
"content": "item content",
"thumbnail_url": "thumbnail URL"
}Behavior:
- Uses
feedas the text-card title. - Uses
myflaskServer Webhook:<title>as the description. - Uses
urlas the card link. - Sends through
conf['bots']['mone_chan'].
These routes proxy temporary WeCom media by first creating a WecomSan client
and using its access token to call the WeCom media API.
Streams raw temporary media from:
https://qyapi.weixin.qq.com/cgi-bin/media/get
Behavior:
- Passes
access_tokenandmedia_idto the WeCom API. - Streams the upstream response body.
- Copies upstream headers except
content-length,connection, andcontent-encoding.
Fetches temporary media as HTML, optionally modifies one redirect link, and
returns text/html; charset=utf-8.
Behavior:
- Downloads the media content from WeCom.
- Detects whether the request
User-AgentcontainsMicroMessenger. - If the HTML contains a matching redirect link to
tvkingdomand the client is WeChat, replaces that link with a JavaScript alert asking the user to open it in a browser. - Returns the modified HTML.
The ddredirect module provides an authenticated dashboard. It is used as a fixed endpoint for redirecting to my home services which are behind dynamic ports (due to STUN NAT piercing).
Information like dynamic IP/port data are stored in config_ddredirect.json and can be automatically updated via a webhook as the ports change.
Dashboard and webhook routes use HTTP Basic Auth from:
config_ddredirect.json -> auth.username / auth.password
Authenticated dashboard page.
Behavior:
- Loads
config_ddredirect.json. - Resolves configured TXT records to discover current DNS-published IPs.
- Renders
routes/ddredirect/templates/dashboard.html. - Shows configured services, IPs, STUN ports, DNS TXT results, and timestamp.
Public IPv4 service endpoint.
Behavior:
- Looks up
service_nameinconfig['services']. - Uses
config['ips']['ipv4']. - For
webservices:- Uses the
ddasus_webSTUN port. - Builds a URL from service scheme, subdomain, domain, configured path, the requested trailing path, and query string.
- Redirects the client to that URL.
- Uses the
- For non-web services:
- Uses the STUN port named after the service.
- Returns plain text containing
ip:portanddomain:port.
Authenticated IPv6 dashboard shortcut. Redirects to /dd/.
Public IPv6 service endpoint.
Behavior:
- Looks up
service_nameinconfig['services']. - Requires the service to define
ipv6_hostandoriginal_port. - Selects the configured IPv6 host IP/domain.
- Resolves DNS TXT records and compares the TXT IP with the configured current IP.
- For
webservices:- Redirects to a domain URL when TXT and configured IP match.
- Otherwise redirects to a bracketed IPv6 literal URL.
- Preserves query string.
- For non-web services:
- Returns plain text with the preferred address on the first line and a fallback address on the second line.
Authenticated webhook for updating an IP entry in config_ddredirect.json.
Expected JSON body:
{
"ip": "new IP address"
}Behavior:
- Validates that
ipis present. - Validates that
ip_typeexists inconfig['ips']. - Updates
config['ips'][ip_type]. - Saves
config_ddredirect.json. - Returns JSON success or error messages.
Authenticated webhook for updating a STUN port and the current IPv4 address.
Expected JSON body:
{
"service_name": "service key",
"port": 12345,
"ip": "new IPv4 address"
}Behavior:
- Validates
service_name,port, andip. - Updates
config['stun_ports'][service_name]. - Updates
config['ips']['ipv4']. - Saves
config_ddredirect.json. - Returns JSON success or error messages.
Proxies the incoming request to the full target URL supplied in the path.
Behavior:
- Copies request headers except
Host. - Replaces
User-Agentwith a Firefox-like desktop user agent. - Forwards query parameters and raw request body.
- Copies upstream response headers and status code back to the client.
- Returns
500with the request exception text on upstream request failure.
Example shape:
/redirect/https://example.com/path
Returns the WeCom verification token:
Ua7WxLfBndo8F2SR
Returns the URL path generated for the local WireGuard proxy route:
/redirectlocal/wireguard/
In the automatically loaded wireguard.py module this endpoint returns the URL
as text. The sibling wireguard_chan.py module contains a redirecting variant
and WeCom command handling for WireGuard service control, but it is not
registered by the current auto-loader.
Health-check style endpoint. Returns the plain text response:
Welcome to wecom_responder!
Blocked to prevent exposure of the service.
Main module enablement is controlled by enabled_modules in
wecom_responder/config.json. Module-specific secrets and bot credentials live
under module_params.
Important module parameter groups:
drink_chan: WeCom receiver token/AES key and bot credentials.subscribe_chan: WeCom receiver token/AES key and bot credentials.temp_media_redirect: bot credentials for fetching WeCom temporary media.webhook: bot credentials for RSS text cards and notification messages.wireguard: bot credentials plus public WireGuard URL.ddredirect: dynamic service data is stored separately inconfig_ddredirect.json.
Do not commit live config.json or config_ddredirect.json if they contain
real tokens, secrets, internal IPs, or Basic Auth credentials.



