From ffd55554392387574c54728252909e84ae954d84 Mon Sep 17 00:00:00 2001 From: ed Date: Sat, 27 Apr 2024 23:04:56 +0000 Subject: [PATCH] v1.6.1 --- README.md | 21 +++++++++++++++++++-- docs/r0c-irc.png | Bin 0 -> 12842 bytes r0c/__version__.py | 4 ++-- r0c/user.py | 2 +- test/stress.py | 5 ++++- 5 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 docs/r0c-irc.png diff --git a/README.md b/README.md index e282ffa..528f4de 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ retr0chat is the lightweight, no-dependencies, runs-anywhere solution for when l * tries to be irssi * zero dependencies on python 2.6, 2.7, 3.x * supports telnet, netcat, /dev/tcp, TLS clients -* is not an irc server, but can bridge to/from irc servers +* is not an irc server, but can [bridge to/from irc servers](#irc) * [modem-aware](https://ocv.me/r0c-2400.webm); comfortable at 1200 bps * fallbacks for inhumane conditions * linemode @@ -31,6 +31,7 @@ retr0chat is the lightweight, no-dependencies, runs-anywhere solution for when l * 1980: [TVI 920C](https://a.ocv.me/pub/g/nerd-stuff/r0c-tvi-920c.jpg) * 1987: [IBM 3151](https://a.ocv.me/pub/g/nerd-stuff/r0c-ibm-3151.jpg) (also [video](https://a.ocv.me/pub/g/nerd-stuff/r0c-ibm-3151.webm)), using gnu-screen to translate VT100 sequences +* 1993: [windows 3.11](https://a.ocv.me/pub/g/nerd-stuff/r0c-for-workgroups.png) ## features @@ -48,7 +49,7 @@ technical: * history of sent messages (arrow-up/down) * bandwidth-conservative (push/pop lines instead of full redraws; scroll-regions) * fast enough; 600 clients @ 750 msgs/sec, or 1'000 cli @ 350 msg/s -* bridge several irc channels from several networks into one r0c channel +* [bridge](#irc) several irc channels from several networks into one r0c channel ## windows clients @@ -108,6 +109,22 @@ you can run it as a service so it autostarts on boot: * on alpine / gentoo: [openrc service](docs/openrc/r0c) * on windows: [nssm](https://nssm.cc/) probably +## irc + +if you want to connect your r0c instance to an irc network and bridge channels between them, you can do that: + +![screenshot of a r0c channel being bridged to an irc channel](docs/r0c-irc.png) + +```bash +python3 r0c.py --ircn a,127.0.0.1,6667,r0c --ircb a,chat,g +``` + +run that command to start r0c with irc bridging enabled; r0c will then connect to an irc server (which we nicknamed `a`) on `127.0.0.1:6667` with the irc-nick `r0c` and bridge the irc-channel `#chat` with the r0c-channel `#g` + +if you then start an irc server locally, for example [miniircd](https://github.com/jrosdahl/miniircd/blob/master/miniircd) by running `python3 miniircd --verbose` then you're all set, people can now join r0c by connecting via irc + +to bridge additional channels on the same network, add more `--ircb` args, for example `--ircb a,tech,tech` like in the screenshot, and optionally add more networks with `--ircn` + ## firewall rules skip this section if: diff --git a/docs/r0c-irc.png b/docs/r0c-irc.png new file mode 100644 index 0000000000000000000000000000000000000000..40754bf5f3987563540e2ac30a33aaec2896be81 GIT binary patch literal 12842 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%0AtUpNAwx(oGmGsiX1*`{l3Iey72P-X&3*YZJ8o` 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