{"id":17101874,"url":"https://github.com/maskray/wechatircd","last_synced_at":"2025-04-06T06:11:20.116Z","repository":{"id":138473148,"uuid":"52097965","full_name":"MaskRay/wechatircd","owner":"MaskRay","description":"㊙用IRC客户端控制微信网页版","archived":false,"fork":false,"pushed_at":"2020-06-22T16:11:06.000Z","size":713,"stargazers_count":407,"open_issues_count":0,"forks_count":43,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-03-30T05:06:40.693Z","etag":null,"topics":["irc-server","wechat"],"latest_commit_sha":null,"homepage":"https://maskray.me/blog/2016-02-21-wechatircd","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MaskRay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-02-19T15:46:24.000Z","updated_at":"2025-03-28T05:14:29.000Z","dependencies_parsed_at":null,"dependency_job_id":"27cd17aa-c0f4-435f-be29-467c65527d1f","html_url":"https://github.com/MaskRay/wechatircd","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaskRay%2Fwechatircd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaskRay%2Fwechatircd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaskRay%2Fwechatircd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaskRay%2Fwechatircd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MaskRay","download_url":"https://codeload.github.com/MaskRay/wechatircd/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247441053,"owners_count":20939239,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["irc-server","wechat"],"created_at":"2024-10-14T15:27:14.977Z","updated_at":"2025-04-06T06:11:20.098Z","avatar_url":"https://github.com/MaskRay.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[简体中文](README.zhs.md)\n\n# wechatircd [![IRC](https://img.shields.io/badge/IRC-freenode-yellow.svg)](https://webchat.freenode.net/?channels=wechatircd) [![Telegram](https://img.shields.io/badge/chat-Telegram-blue.svg)](https://t.me/wechatircd) [![Gitter](https://img.shields.io/badge/chat-Gitter-753a88.svg)](https://gitter.im/wechatircd/wechatircd)\n\nwechatircd injects JavaScript (`injector.js`) to wx.qq.com, which uses WebSocket to communicate with an IRC server (`wechatircd.py`), thus enable IRC clients connected to the server to send and receive messages from WeChat, set topics, invite/delete members, ...\n\n```\n           IRC               WebSocket                 HTTPS\nIRC client --- wechatircd.py --------- browser         ----- wx.qq.com\n                                       injector.user.js\n                                       injector.js\n```\n\nDiscuss wechatircd by joining #wechatircd on freenode, or the [user group on Telegram](https://t.me/wechatircd).\n[Video on using WeChat in WeeChat](https://asciinema.org/a/636dkay05bpzci1idf3e84y1y)\n\n## Installation\n\n- [Arch Linux](#arch-linux) or [Not Arch Linux](#not-arch-linux)\n- [Userscript and self-signed certificate](#userscript-and-self-signed-certificate)\n- [Usage](#usage)\n\n### Arch Linux\n\n- `yaourt -S wechatircd-git`. It will generate a self-signed CA key/certificate pair `/etc/wechatircd/ca.{cert,key}.pem` and a key/certificate pair `{cert,key}.pem` (see below).\n- Import the CA certificate `/etc/wechatircd/ca.cert.pem` to the browser (see below).\n- `systemctl start wechatircd`, which runs `/usr/bin/wechatircd --http-cert /etc/wechatircd/cert.pem --http-key /etc/wechatircd/key.pem --http-root /usr/share/wechatircd`. You may want to customize `/etc/systemd/system/wechatircd.service`.\n\n`wechatircd.py` (the server) will listen on 127.0.0.1:6667 (IRC) and 127.0.0.1:9000 (HTTPS + WebSocket over TLS).\n\nIf you run the server on another machine, it is recommended to set up IRC over TLS and an IRC connection password with a few more options: `--irc-cert /path/to/irc.key --irc-key /path/to/irc.cert --irc-password yourpassword`. As an alternative to the IRC connection password, you may specify `--sasl-password yourpassword` and authenticate with SASL PLAIN. You can reuse the HTTPS certificate+key. If you use WeeChat and find it difficult to set up a valid certificate (gnutls checks the hostname), type the following lines in WeeChat:\n```\n/set irc.server.wechat.ssl on\n/set irc.server.wechat.ssl_verify off\n/set irc.server.wechat.password yourpassword\n```\n\n### Not Arch Linux\n\n- python \u003e= 3.5\n- `pip install -r requirements.txt`\n- ```zsh\n  openssl req -x509 -newkey rsa:2048 -sha256 -nodes -keyout ca.key.pem -out ca.cert.pem -days 9999 -subj '/CN=127.0.0.1'\n  openssl req -new -newkey rsa:2048 -sha256 -nodes -keyout key.pem -subj '/CN=127.0.0.1' |\n    openssl x509 -req -out cert.pem -CAkey ca.key.pem -CA ca.cert.pem -set_serial 2 -days 9999 -extfile \u003c(\n      printf \"subjectAltName = IP:127.0.0.1, DNS:localhost\")\n  ```\n- Import the CA certificate `ca.cert.pem` to the browser.\n- `./wechatircd.py --http-cert cert.pem --http-key key.pem`\n\nThe IP address or the domain name used to serve `injector.js` and `injector.user.js` should match the `subjectAlternativeName` fields. Chrome has removed support for `commonName` matching in certificates since version 58. See \u003chttps://developers.google.com/web/updates/2017/03/chrome-58-deprecations#remove_support_for_commonname_matching_in_certificates\u003e for detail.\n\n## Userscript and self-signed CA certificate\n\nChrome/Chromium\n\n- Visit `chrome://settings/certificates`，import `ca.cert.pem`，click the `Authorities` tab，select the `127.0.0.1` certificate, Edit-\u003eTrust this certificate for identifying websites.\n- Install extension Tampermonkey, install \u003chttps://github.com/MaskRay/wechatircd/raw/master/injector.user.js\u003e. It will inject \u003chttps://127.0.0.1:9000/injector.js\u003e to \u003chttps://wx.qq.com\u003e. You need to change `127.0.0.1:9000` if you want wechatircd to listen on another address.\n\nFirefox\n\n- Install extension Greasemonkey，install the userscript.\n- Visit \u003chttps://127.0.0.1:9000/injector.js\u003e, Firefox will show \"Your connection is not secure\", Advanced-\u003eAdd Exception-\u003eConfirm Security Exception\n\n![](https://maskray.me/static/2016-02-21-wechatircd/meow.jpg)\n\nThe server serves `injector.js` and WebSocket connections on 127.0.0.1:9000 by default, which can be overriden with `--http-listen 0.0.0.0 --http-port 9000`.\n\nYou can enable HTTPS in two ways:\n\n- `--http-cert cert.pem --http-key key.pem` to make wechatircd serve HTTPS\n- Omit `--http-cert --http-key` to make wechatircd serve HTTP, and use Nginx (with HTTPS enabled) as a reverse proxy. In this case, you need to pass `Host:` to wechatircd (`proxy_set_header Host $http_host;`) as it changes the WebSocket URL defined in `injector.js` according to `Host:` specified by the browser.\n\n## Usage\n\n- Run `wechatircd.py`\n- Visit \u003chttps://wx.qq.com\u003e, the injected JavaScript will create a WebSocket connection to the server\n- Open devtools, and run `injector.run()`\n- Connect to 127.0.0.1:6667 in your IRC client\n\nYou will join `+wechat` channel automatically and find your contact list there. Some commands are available:\n\n- `help`\n- `eval`, eval a Python expression, such as: `eval server.nick2special_user` `eval server.name2special_room`\n- `status`, show contacts/channels\n- `reload_contact __all__`, reload all contact info in case of `no such nick/channel` in privmsg\n\nThe server can only be bound to one wx.qq.com account, however, you may have more than one IRC clients connected to the server.\n\n## IRC features\n\n- Standard IRC channels have names beginning with `#`.\n- WeChat groups have names beginning with `\u0026`. The channel name is generated from the group title. `SpecialChannel#update`\n- Contacts have modes `+v` (voice, usually displayed with a prefix `+`). `SpecialChannel#update_detail`\n- Multi-line messages: `!m line0\\nline1`\n- Multi-line messages: `!html line0\u003cbr\u003eline1`\n- `nick0: nick1: test` will be converted to `@GroupAlias0 @GroupAlias1 test`, where `GroupAlias0` is `My Alias in Group`/`Name` in profile/`WeChat ID` set by that user. It corresponds to `On-screen names` in the mobile application.\n- Reply to the message at 12:34:SS: `@1234 !m multi\\nline\\nreply`, which will be sent as `「Re GroupAlias: text」text`\n- Reply to the message at 12:34:56: `!m @123456 multi\\nline\\nreply`\n- Reply to the penultimate message (your own messages are not counted) in this channel/chat: `@2 reply`\n- Paste detection. Lines will be hold for up to 0.1 seconds before sending, lines in this interval will be packed to a multiline message\n- `--http-url https://127.0.0.1:9000` if you want to shorten media URLs to something like `https://127.0.0.1:9000/media/0`\n\n`!m `, `@3 `, `nick: ` can be arranged in any order.\n\nFor WeeChat, its anti-flood mechanism will prevent two user messages sent to IRC server in the same time. Disable anti-flood to enable paste detection.\n```\n/set irc.server.wechat.anti_flood_prio_high 0\n```\n\n`server-time` extension from IRC version 3.1, 3.2. `wechatircd.py` includes the timestamp (obtained from JavaScript) in messages to tell IRC clients that the message happened at the given time. See \u003chttp://ircv3.net/irc/\u003e. See\u003chttp://ircv3.net/software/clients.html\u003e for Client support of IRCv3.\n\nConfiguration for WeeChat:\n```\n/set irc.server_default.capabilities \"account-notify,away-notify,cap-notify,multi-prefix,server-time,znc.in/server-time-iso,znc.in/self-message\"\n```\n\nSupported IRC commands:\n\n- `/cap`, supported capabilities.\n- `/dcc send $nick/$channel $filename`, send image or file。This feature borrows the command `/dcc send` which is well supported in IRC clients. See \u003chttps://en.wikipedia.org/wiki/Direct_Client-to-Client#DCC_SEND\u003e.\n- `/invite $nick [$channel]`, invite a contact to the group.\n- `/kick $nick`, delete a group member. You must be the group leader to do this. Due to the defect of the Web client, you may not receive notifcations about the change of members.\n- `/kill $nick [$reason]`, cause the connection of that client to be closed\n- `/list`, list groups.\n- `/mode +m`, no rejoin in `--join new` mode. `/mode -m` to revert.\n- `/motd`, view latest 5 commits of this repo\n- `/names`, update nicks in the channel.\n- `/part [$channel]`, no longer receive messages from the channel. It just borrows the command `/part` and it will not leave the group.\n- `/query $nick`, open a chat window with `$nick`.\n- `/squit $any`, log out\n- `/summon $nick $message`，add a contact.\n- `/topic topic`, change the topic of a group. Because IRC does not support renaming of a channel, you will leave the channel with the old name and join a channel with the new name.\n- `/who $channel`, see the member list.\n\n![](https://maskray.me/static/2016-02-21-wechatircd/demo.jpg)\n\n### Display\n\n- `MSGTYPE_TEXT`，text, or invitation of voice/video call\n- `MSGTYPE_IMG`，image, displayed as `[Image] $url`\n- `MSGTYPE_VOICE`，audio, displayed as `[Voice] $url`\n- `MSGTYPE_VIDEO`，video, displayed as `[Video] $url`\n- `MSGTYPE_MICROVIDEO`，micro video?，displayed as `[MicroVideo] $url`\n- `MSGTYPE_APP`，articles from Subscription Accounts, Red Packet, URL, ..., displayed as `[App] $title $url`\n\nQQ emojis are displayed as `\u003cimg class=\"qqemoji qqemoji0\" text=\"[Smile]_web\" src=\"/zh_CN/htmledition/v2/images/spacer.gif\"\u003e`, `[Smile]` in sent messages will be replaced to emoticon.\n\nEmojis are rendered as `\u003cimg class=\"emoji emoji1f604\" text=\"_web\" src=\"/zh_CN/htmledition/v2/images/spacer.gif\"\u003e`. Each emoji will be converted to a single character before delivered to the IRC client. Emojis may overlap as terminal emulators may not know emojis are of width 2，see [终端模拟器下使用双倍宽度多色Emoji字体](https://maskray.me/blog/2016-03-13-terminal-emulator-fullwidth-color-emoji).\n\n## Server options\n\n- `--config`, short option `-c`, config file path, see [config](config)\n- HTTP/WebSocket related options\n  + `--http-cert cert.pem`, TLS certificate for HTTPS/WebSocket. You may concatenate certificate+key, specify a single PEM file and omit `--http-key`. Use HTTP if neither `--http-cert` nor `--http-key` is specified.\n  + `--http-key key.pem`, TLS key for HTTPS/WebSocket\n  + `--http-listen 127.1 ::1`, change HTTPS/WebSocket listen address to `127.1` and `::1`, overriding `--listen`\n  + `--http-port 9000`, change HTTPS/WebSocket listen port to 9000\n  + `--http-root .`, the root directory to serve `injector.js`\n  + `--http-url https://127.0.0.1:9000`, if specified, display media links as https://127.0.0.1:9000/document/$id ; if not, `https://wx.qq.com/cgi-bin/...`\n- Groups that should not join automatically. This feature supplements join mode.\n  + `--ignore '\u0026fo[o]' '\u0026bar'`, do not auto join channels whose names(generated from Group Name) partially match regex `\u0026fo[o]` or `\u0026bar`\n  + `--ignore-display-name 'fo[o]' bar`, short option `-I`, do not auto join channels whose Group Name partially match regex `fo[o]` or `bar`\n- `--ignore-brand`, ignore messages from subscription accounts (`MM_USERATTRVERIFYFALG_BIZ_BRAND`)\n- IRC related options\n  + `--irc-cert cert.pem`, TLS certificate for IRC over TLS. You may concatenate certificate+key, specify a single PEM file and omit `--irc-key`. Use plain IRC if neither --irc-cert nor --irc-key is specified.\n  + `--irc-key key.pem`, TLS key for IRC over TLS.\n  + `--irc-listen 127.1 ::1`, change IRC listen address to `127.1` and `::1`, overriding `--listen`.\n  + `--irc-nicks ray ray1`, reverved nicks for clients. `SpecialUser` will not have these nicks.\n  + `--irc-password pass`, set the connection password to `pass`.\n  + `--irc-port 6667`, IRC server listen port.\n- Join mode, short option `-j`\n  + `--join auto`, default: join the channel upon receiving the first message, no rejoin after issuing `/part` and receiving messages later\n  + `--join all`: join all the channels\n  + `--join manual`: no automatic join\n  + `--join new`: like `auto`, but rejoin when new messages arrive even if after `/part`\n- `--listen 127.0.0.1`, short option `-l`, change IRC/HTTP/WebSocket listen address to `127.0.0.1`.\n- Server side log\n  + `--logger-ignore '\u0026test0' '\u0026test1'`, list of ignored regex, do not log contacts/groups whose names partially match\n  + `--logger-mask '/tmp/wechat/$channel/%Y-%m-%d.log'`, format of log filenames\n  + `--logger-time-format %H:%M`, time format of entries of server side log\n- `--paste-wait 0.1`, lines will be hold for up to 0.1 seconds before sending, lines in this interval will be packed to a multiline message\n- `--sasl-password pass`, set the SASL password to `pass`.\n- `--special-channel-prefix`, choices: `\u0026`, `!`, `#`, `##`, prefix for SpecialChannel. [Quassel](quassel-irc.org) does not seem to support channels with prefixes `\u0026`, `--special-channel-prefix '##'` to make Quassel happy\n\nSee [wechatircd.service](wechatircd.service) for a template of `/etc/systemd/system/wechatircd.service`.\n\n## Changes in `injector.js`\n\n- Create a WebSocket connection to the server and retry on failures.\n- Hook `contactFactory#{addContact,deleteContact}` to watch changes to the contacts.\n- `CtrlServer#onmessage`, handle commands (text/file messages, invite someone to the group, ...) from the server.\n- `CtrlServer#seenLocalID`, prevent the client from receiving messages sent by itself.\n\n## `wechatircd.py`\n\n\n```\n.\n├── Web                      HTTP(s)/WebSocket server\n├── Server                   IRC server\n├── Channel\n│   ├── StandardChannel      IRC channels\n│   ├── StatusChannel        `+wechat`\n│   └── SpecialChannel       WeChat groups\n├── (User)\n│   ├── Client               IRC clients\n│   ├── SpecialUser          WeChat users\n├── (IRCCommands)\n│   ├── UnregisteredCommands available commands: CAP NICK PASS USER QUIT\n│   ├── RegisteredCommands\n```\n\n## FAQ\n\n### Motivation\n\n- Replace the mobile application with your IRC client. See [WeeChat操作各种聊天软件](https://maskray.me/blog/2016-08-13-weechat-rules-all).\n- Bot\n- Log. It is difficult to export log from the mobile client \u003chttps://maskray.me/blog/2014-10-14-wechat-export\u003e\n\nIf you cannot tolerant scanning QR codes with your phone everyday, see [无需每日扫码的IRC版微信和QQ：wechatircd、webqqircd](https://maskray.me/blog/2016-07-06-wechatircd-webqqircd-without-scanning-qrcode-daily).\n\n## Fetch data \u0026 control wx.qq.com\n\nSome special accounts' `UserName` do not have the `@` prefix: `newsapp,fmessage,filehelper,weibo,qqmail,fmessage`。Standard accounts' `UserName` start with `@`; Groups' `UserName` start with `@@`。`UserName` are different among sessions. `Uin` looks like an unique identifier, but most of the time its value is 0.\nA group's `OwnerUin` is the owners's `Uin`，but most of the time `Uin` is 0.\n\nMy account\n```javascript\nangular.element(document.body).scope().account\n```\n\nList of all contacts\n```javascript\nangular.element($('#navContact')[0]).scope().allContacts\n```\n\nDelete a member from a group\n```javascript\nvar injector = angular.element(document).injector()\n# 这里获取了chatroomFactory，还可用于获取其他factory、service、controller等\nvar chatroomFactory = injector.get('chatroomFactory')\n# 设置其中的`room`与`userToRemove`\nchatroomFactory.delMember(room.UserName, userToRemove.UserName)`\n```\n\nSend a message to the current chat\n```javascript\nangular.element('pre:last').scope().editAreaCtn = \"Hello，微信\";\nangular.element('pre:last').scope().sendTextMessage();\n```\n\n### Headless browser on Linux\n\nIf you cannot tolerant scanning QR codes with your phone everyday, you can run the browser and wechatircd on a server.\n\n- Create a new browser user profile with `chromium --user-data-dir=$HOME/.config/chromium-wechatircd`, and do the aforementioned configuration (certificate for `injector.js`, Tampermonkey, `injector.user.js`), then close the browser.\n- Install xvfb (`xorg-server-xvfb` on Arch Linux)\n- `xvfb-run -n 99 chromium --user-data-dir=$HOME/.config/chromium-wechatircd https://wx.qq.com`\n- Wait a few seconds for the QR code. `DISPLAY=:99 import -window root /tmp/a.jpg \u0026\u0026 $your_image_viewer /tmp/a.jpg`, take a screenshot and scan the QR code with your mobile application.\n\nYou can interact with the browser using VNC:\n\n- `x11vnc -localhost -display :99`\n- In another terminal, `vncviewer localhost`\n\nAn alternative is x2go, see [无需每日扫码的IRC版微信和QQ：wechatircd、webqqircd](https://maskray.me/blog/2016-07-06-wechatircd-webqqircd-without-scanning-qrcode-daily).\n\n### How are nicks generated?\n\nOn the mobile application, users' `On-screen Names` are resolved in this order:\n- `Set Remark and Tag` if set\n- `My Alias in Group`(`Group Alias`) if set\n- `Name` in his/her profile\n- `WeChat ID`\n\nContact information is given in APIs `batchgetcontact` and `webwxsync`. The JSON serialization uses misleading field names.\n\nWeChat friend in `contactFactory#addContact`:\n\n- `.Alias`: `Name` in his/her profile\n- `.NickName`: `WeChat ID`\n- `.RemarkName`: `Set Remark and Tag`\n\nWeChat friend/non-contact in `.MemberList`:\n\n- `.DisplayName`: `My Alias in Group`\n- `.NickName`: `Name` in his/her profile or `WeChat ID`\n\nJSON for one user may be returned repeatedly and all these fields may be empty. Users' nicks are generated by looking for the first non-empty value from these fields: `.RemarkName`, `.NickName`, `.DisplayName`. You may see `xx now known as yy` in your IRC client if a room contact shares multple rooms with you.\n\n## Known issues\n\n### `Uncaught TypeError: angular.extend is not a function`\n\nYou may see these messages in the DevTools console:\n\n```\nUncaught TypeError: angular.extend is not a function\n    at Object.setUserInfo (index_0c7087d.js:4)\n    at index_0c7087d.js:2\n    at c (vendor_2de5d3a.js:11)\n    at vendor_2de5d3a.js:11\n    at c.$eval (vendor_2de5d3a.js:11)\n    at c.$digest (vendor_2de5d3a.js:11)\n    at c.$apply (vendor_2de5d3a.js:11)\n    at l (vendor_2de5d3a.js:11)\n    at m (vendor_2de5d3a.js:11)\n    at XMLHttpRequest.C.onreadystatechange (vendor_2de5d3a.js:11)\n```\n\n```\nUncaught TypeError: angular.forEach is not a function\n```\n\n`injector.js` should be executed after `vendor_*.js` and before `index_*.js`. However, TamperMonkey cannot finely control the execution time due to the limitation of Chrome.\n\n### Cannot send/receive new messages when the webpage disconnects from wx.qq.com\n\nThe WebSocket connection to `wechatircd.py` should be closed in this case, let users know they should reload the webpage.\n\n### Others\n\n- Log filenames may contain invalid filenames (`:`) on Windows\n- Stable channel names. This makes server-side log coherent and users will not be distracted by `PART (Change name)` `JOIN` messages. Channel names are generated from `.NickName` (Group Name) and Group Name may change. I do not know any persistent ID of an account/group because `UserName` changes in each new session.\n\n## References\n\n- [miniircd](https://github.com/jrosdahl/miniircd). Copied a lot of protocol related stuff from miniircd.\n- [RFC 2810: Internet Relay Chat: Architecture](https://tools.ietf.org/html/rfc2810)\n- [RFC 2811: Internet Relay Chat: Channel Management](https://tools.ietf.org/html/rfc2811)\n- [RFC 2812: Internet Relay Chat: Client Protocol](https://tools.ietf.org/html/rfc2812)\n- [RFC 2813: Internet Relay Chat: Server Protocol](https://tools.ietf.org/html/rfc2813)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaskray%2Fwechatircd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaskray%2Fwechatircd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaskray%2Fwechatircd/lists"}