Git Product home page Git Product logo

matrix-appservice-sms's Introduction

matrix-appservice-sms

What is this?

This is a Matrix.org Application Service (AS) that bridges SMS messages to Matrix, using a USB 3G modem plugged into a server. Crucially, it only works for one user - obviously, if you only have one 3G modem, it doesn't really make sense to support more than one user...

What do I need to run it?

  • an instance of PostgreSQL
  • a Huawei USB 3G modem, like the Huawei E3531, or Huawei E169
    • Other models of 3G modem are available. Essentially, if it uses the AT/Hayes command set, and implements a bunch of common commands, it'll probably work.
    • This has been tested working with the Huawei E3531, though.
  • a nightly version of Rust; see below for details
  • a decent amount of patience ;p

You may also be interested in sms-irc, which is in many ways the successor to this project. This project isn't that maintained at the moment, with work mainly being focused on sms-irc, but PRs and issues are still very much welcome and will receive attention!

How do I set this up?

Oh, man.

Set up the 3G modem

  • Firstly, ensure that your 3G modem presents itself as a serial port - usually with a path like /dev/ttyUSBX.
    • Advice is available on the Arch Wiki, and varies from model to model. You might need to do a bit of googling to figure out how to poke your modem into appearing as a serial device, as many appear as mass storage devices with software by default.
    • For the Huawei E3531, try sudo usb_modeswitch -v 12d1 -p 15cd -M '55534243123456780000000000000011062000000100000000000000000000'.
      • If that doesn't work, try changing the 12d1 and 15cd above with whatever VID:PID combo appears next to the device in lsusb.
      • For example, if your device presents itself as a ID 12d1:1506 Huawei Technologies Co., Ltd. Modem/Networkcard when lsusb is run, you'd use -v 12d1 and -p 1506.
      • Again, this stuff is really dependent on your modem. Google is your friend, if the above device didn't work for you!
    • Some modems (like the E3531) present three serial ports: /dev/ttyUSB0-2. You want /dev/ttyUSB2 in this case.
    • Once you've found the device path for your modem, try connecting to it with sudo minicom -D /dev/ttyUSB2 (replacing /dev/ttyUSB2 with the path for your modem if different), and typing AT<Enter>. If you get OK back, you've found the right path!
  • Also ensure that the user you're going to run the AS as can read and write to this serial port. (sudo chmod 777 /dev/ttyUSB2 does the job, but is pretty bad security-wise; it's better to configure users and groups correctly.)

Set up Rust

  • You need the latest nightly version of Rust installed; check out their install page. If you install with rustup, change the default configuration when prompted to install the nightly toolchain.
    • NB: As of 2018-05-24, this project only works with rustc 1.27.0-nightly (e5f80f2a4 2018-05-09) - override your toolchain to use that nightly!
    • This can be done with $ rustup override set nightly-2018-05-10.
  • Build the project with cargo build.
  • Then, install diesel_cli with cargo install diesel_cli.

Set up the database

  • Run DATABASE_URL=[url] diesel migration run, substituting [url] for your database URL (e.g. postgresql://localhost/database).

Set up synapse

  • Replace the placeholders in sms-registration.yaml with sane values (for the tokens and id, generate some random crap, but make sure all of the values are different; for the URL, put the URL of where you're going to put your matrix-appservice-sms instance).
  • Copy this somewhere (usually /etc/synapse) readable by synapse.
  • Edit app_service_config_files in your synapse homeserver.yaml, and add the path to your sms-registration.yaml file. e.g.:
app_service_config_files: ["/etc/synapse/sms-registration.yaml"]
  • (Hold off on restarting synapse for now; we want to make sure that the AS is reachable first.)

Set up the AS

  • Replace the placeholders in Rocket.example.toml, following the guidance therein, and rename it to Rocket.toml.
  • Run the AS with cargo run.
  • Now, restart synapse.

Use the AS

  • Invite @_sms_bot:[your HS] to a 1-1 chat.
  • Issue !sms [phone number] in that chatroom to start texting! (You'll get invited to a private chat with that phone number.) Make sure the number is in international format (e.g. +440123456789) for best results.

Your setup instructions are crap! / It didn't work!

License

  • This is GPLv3-licensed software.

matrix-appservice-sms's People

Contributors

eeeeeta avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

ashikabi

matrix-appservice-sms's Issues

quota management

i.e. keep a track of SMSes sent, and allow for configurable warnings in order to manage pay-as-you go SIMs and stuff

don't drop messages on the floor

As seen in #13, if we fail to deliver a message, it just gets dropped on the floor. That's less than ideal. Ideally, we'd stash it in the DB somewhere, and retry delivery with a backoff, alerting the user (if possible) that this is happening.

message sent counter?

People running the bridge may want to keep a track of how many messages they've sent, in order to figure out when they need to top up a PAYG SIM. We should keep a track of that in the DB, and alert the user in the admin room at 90%, 95%, etc. of quota used (where the quota should be user-configurable).
(Also, if we wanted to go full Snapchat, we could adapt this feature into one of those garbage messages sent:received ratio things...)

Deal forwarding SMS to multiple users

It would be great to do that in order to use a SIM card as a family number, forwarding messages to all family members, and being able to forward answers and conversations to people using SMS. That would also be great in order to do conferencing including multiple users on both sides

Don't send old events

When starting back up, refuse to send events with an origin_server_ts too far back in the past. Also, warn loudly about dropping said messages.

handle SMS-SUBMIT PDUs in message memory

This was a bit of a stupid oversight.

If you use your modem with software that sends SMS-SUBMIT PDUs and stores them in the STO SENT/STO UNSENT memory, our parser breaks, because it currently only expects SMS-DELIVER PDUs despite asking for all messages (including outgoing ones). This is stupid. We should do one of the following:

  • not ask for messages we can't handle
  • figure out which PDU type it is by which memory store it's in, and parse intelligently

We should also, like, consider making AT+CMGL more failure-tolerant. If one person sends you a bad PDU (although that shouldn't be doable), they could break everything. That's no fun.

if future dies, the whole bridge gets wedged & doesn't restart properly

matrix-appservice-sms[2275]: note: Run with `RUST_BACKTRACE=1` for a backtrace.
matrix-appservice-sms[2275]: thread '<unnamed>' panicked at 'urc_rx stopped producing', libcore/option.rs:917:5
matrix-appservice-sms[2275]: Error: HuaweiModemFuture failed: an error occurred when formatting an argument
matrix-appservice-sms[2275]: Sending part 1/1...

essentially, we need the whole bridge to crash & burn whenever the future dies, so systemd can restart it. otherwise, requests just 500 and everything stops.

handle multiple SMSes from a new user in one go

this is stupid:

May 22 14:13:54 nichtsdestoweniger matrix-appservice-sms[20290]: +CMGL complete
May 22 14:13:54 nichtsdestoweniger matrix-appservice-sms[20290]: Processing message received from 3Message
May 22 14:13:54 nichtsdestoweniger matrix-appservice-sms[20290]: Processing message received from 3Message
May 22 14:13:54 nichtsdestoweniger matrix-appservice-sms[20290]: Registering new user @_sms_D0517710111511597103101:theta.eu.org
May 22 14:13:54 nichtsdestoweniger matrix-appservice-sms[20290]: Registering new user @_sms_D0517710111511597103101:theta.eu.org
May 22 14:13:55 nichtsdestoweniger matrix-appservice-sms[20290]: Creating new room
May 22 14:13:55 nichtsdestoweniger matrix-appservice-sms[20290]: Creating new room
May 22 14:13:55 nichtsdestoweniger matrix-appservice-sms[20290]: Error: Failed to process received message: Error from homeserver: BadRequestReply { errcode: "M_UNKNOWN", error: Some("Room alias already taken") }        

Essentially, we need to create a new table for new users, and do some fancy SQL locking magic to ensure that only one person tries to create a new user at a time.

Actually, wait, no, that ain't gonna work, because this is futures, so we can't do locking. You'd probably use a mutex.

Except we ain't got none of those, because this is futures. So, I guess we just use message-passing like it says in that issue thread, and make new-user-messages linear. That'd probably work.

Message polling behaviour to make delivery more robust / if CNMI fails

  1. Our reception of new messages is entirely dependent on CNMI indications; we should probably also poll every so often, just to be doubly sure
  2. Currently, the bridge just flat-out breaks if your modem doesn't support sending +CNMI indications on new messages.

So yeah, we probably need some polling functionality as well.

do an AT+CMGL on boot & poll for messages periodically

if the bridge crashes, we want to ensure that we read any messages when the bridge starts up again, so stuff gets delivered. currently we just wait for +CNMI, which is less than ideal.
(come to think of it, polling for messages every ~10min or something wouldn't be a bad idea either)

log errors to admin room

Currently, we just log errors to stdout, which doesn't help anybody except the most vigilant of server admins. We should also log errors to the admin room, so the user actually knows when things go wrong.

Fix media URLs

Currently, sending images &c is kinda borked, because the recipient just gets a mxc:// URL.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.