twofer 0.3.1.1
Twofer is a 'tweet transfer agent' server / client.
License: MIT
Keywords: twitter

# Twofer

Twofer is a 'tweet transfer agent' server / client.

## Introduction

### Features

1. A server / client architecture &mdash; It helps you creating various Twitter bots easily.
2. Pure Twitter API v2 &mdash; You can run your Twofer server with a [Twitter Essential Access](https://developer.twitter.com/en/docs/twitter-api/getting-started/about-twitter-api) account.

### Requirements

- I'm testing the code only on the current stable version of Python (3.10 at the time).
- A Twitter developer account (essential / elevated access). You can get it for free from [Twitter Devloper Platform](https://developer.twitter.com/en).
- Any reverse-proxy server for HTTPS (details bellow).

### Project sites

- [emptypage / twofer — Bitbucket](https://bitbucket.org/emptypage/twofer/)
- [twofer · PyPI](https://pypi.org/project/twofer/)
- [emptypage/twofer - Docker Image | Docker Hub](https://hub.docker.com/r/emptypage/twofer)


## Install

Twofer is written in [Python](https://www.python.org) and prvided as a Python package through [PyPI](https://pypi.org). To install:

    $ pip install twofer

The command above will install:

- The `twofer` package, which contains server and client scripts.
- The command-line script, `twofer` for the server and `tf` for the client.


## Server

First of all, you will need to set up a Twofer server for clients unless you will use the other Twofer server which is already ready for you.

### Start the server

To launch the server:

    $ python3 -m twofer.server

or just:

    $ twofer

These are the equivalent.

You may see some errors / exceptions when you just type the command above. It is essential to configure environment values on `.env` or `twofer-server.env` file on the working directory. See the next section.


### Environment variables

The all Twofer server configurations are controlled by its operating system's environment variables, and some of them are essential for running. This section describes the details about these variables.

The environment variables are given to the server through the top part of a command line or shell's `export` command of course, you can specify them for the server via files named `.env` or `twofer-server.env` on the **current working directory**.

Each variable is specified in _dot-env_ files are like:

    VARIABLE_NAME=some_value

I recommend that you specify all these variables explicitly int the file.

#### `TWOFER_TWITTER_CLIENT_ID` [requied]

A 'client ID' for the App.

Note that modern Twitter apps which only support OAuth 2.0 don't use 'consumer key (API key secret)' and 'consumer secret (API sectret)' any longer unlike the other old apps. Don't confuse these variables with them.

#### `TWOFER_TWITTER_CLIENT_SECRET` [requied]

A 'client secret' for the App.

#### `TWOFER_TWITTER_BEARER_TOKEN` [requied]

A 'bearer token' for the App.

#### `TWOFER_FLASK_SECRET_KEY` [requied]

This value is used as a key to generate secure tokens by Flask framework. If you don't know how to get a good secret key, try:

    $ python3 -c "import secrets; print(secrets.token_urlsafe())"
    agDno_q8tG4b02TRgcLKuiO3Lb8qQK_M8I5GKoE6qP4

(The output above is just an instance, of course; **DO NOT USE IT!**)

#### `TWOFER_SERVER_HOST` [optional, default=`localhost`]

Host name that server is listening requests.

#### `TWOFER_SERVER_PORT` [optional, default=`8080`]

Listening port number.

#### `TWOFER_SERVER_GATEWAY_URL` [optional, default=`https://localhost`]

The gateway URL, which is the actual URL that clients send requests. It must starts with `https://`.

#### `TWOFER_SERVER_DATA_FILE` [optional, default=`twofer-server-data.json`]

Path for the JSON file that the Twofer server stores its data.

#### `TWOFER_SERVER_OWNER` [optional, default=_(empty string)_]

Owner's Twitter username (without starting '@').

If you specify the owner account, **every user that the account follows can use the server with a Twofer client**.

#### `TWOFER_SERVER_MEMBERS` [optional, default=_(empty string)_]

Comma separated Twitter user names (without starting '@') that you allow to use the server.

#### A example of `.env` / `twofer-server.env` file

    TWOFER_TWITTER_CLIENT_ID=blNPTmRBejcxNnprakZvWllPXzc6MTpjaQ
    TWOFER_TWITTER_CLIENT_SECRET=iMH4BLyTc_VOPgesq1r8q5NwV2vzmiE9nTd8r1WHSC1CIEgixb
    TWOFER_TWITTER_BEARER_TOKEN=AAAAAAAAAAAAAAAAAAAAABIoggEAAAAAzvKdeA9YMT%2Fj1gvjo5H%2Fa%2B1D47Q%3DICIECKDUa1KeoS3z17suc6FwFz9tdV8ZN6pTXSOKWfcW5UK82F
    TWOFER_FLASK_SECRET_KEY=jigh1OhYash7uayasobief7viwoV3ieHeuFo0vaimooshahp
    TWOFER_SERVER_HOST=127.0.0.1
    TWOFER_SERVER_PORT=8080
    TWOFER_SERVER_GATEWAY_URL=https://localhost
    TWOFER_SERVER_DATA_FILE=${PWD}/twofer-server-data.json
    TWOFER_SERVER_OWNER=_mshibata
    TWOFER_SERVER_MEMBERS=

**WARNING:** The values listed for the variables above as `TWOFER_TWITTER_CLIENT_ID`, `TWOFER_TWITTER_CLIENT_SECRET`, `TWOFER_TWITTER_BEARER_TOKEN` and `TWOFER_FLASK_SECRET_KEY` are sample statement and cannot be used on your site. You have to get these values from your [Twitter Developer Portal](https://developer.twitter.com/en/portal) or by yourself. Needless to say, the rest of the variables are also configured properly to suit your environment too.

### TLS gateway

The Twofer server has to be connected via HTTPS connection because the OAuth 2.0 protocol (which the Twitter API v2 uses) requires to do so, and the `twofer` package itself doesn't have any implementation for SSL / TLS connection.

What does that mean? **It means that you have to set up a so-called reverse-proxy server which works for the backend Twofer server (even if you are going to run the server on `localhost`).** I recommend [Nginx](https://nginx.org) for its purpose, but any program you favor will be OK to do the job.

Let's talk about the certifications for TLS. If you want to run the server on a public Internet domain, [Let's Encrypt](https://letsencrypt.org) is always your best friend. If you plan to set up the server on `localhost`, I recommend to consider using [Minica](https://github.com/jsha/minica). Don't waste your time fighting with complex `openssl` arguments!

Here's an example of `default.conf` for Nginx:

    server {
        listen 443 ssl;
        server_name localhost;
        ssl_certificate /etc/nginx/ssl/localhost/cert.pem;
        ssl_certificate_key /etc/nginx/ssl/localhost/key.pem;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        location / {
            proxy_pass "http://localhost:8080";
        }
    }

### Start the server (again)

After you configured the environment _dot-env_ file, set up the reverse-proxy and hit a `twofer` command on the shell, try open the URL that you specified for `TWOFER_SERVER_GATEWAY_URL` with the Web browser. If you see a simple landing page saying "Welcome to Twofer", congraturations, you (probably) successfully launched your own Twofer server! Check if it works with `tf`, the Twofer client command on another Terminal session.


## Client

To run the Twofer client:

    $ python3 -m twofer.client

or just:

    $ tf

These are equivalent.

The `tf` command is used with sub-commands. Every sub-command has `-h` / `--help` option to show its usage. e.g. `tf create -h`

### `tf init`

    $ tf init

This is the first sub-command you will use.

When you hit the command, it asks what server do you want to use (`localhost`, `twofer.example.com`, etc.).

Then, it shows a URL to authenticate your Twitter account for the server (note: not for client). Open the URL with your Web broser, and authenticate the app, then you will be redirected to the Twofer server landing page which shows a 'user token'. Copy the token and paste into the client input on the shell. After the client stores its token to its data file, you can create / delete tweets with it now.

### `tf login`

    $ tf login

It shows a URL to login to the server Web site. Generally, your browser will sotre your user token on the server web site for convenience with Cookie. The information is used to show your current accout that the client represents. It is also needed for leaving the site via the site. In case of your browser removing the Cookie, you can re-login the site with a URL it shows.

### `tf create`

    $ tf create [file]

This is the sub-command to post a new tweet. When you hit the sub-command without a argument. It shows prompt and ask what to post.

    $ tf create
    What's happening?:

Enter some text and hit Enter key, then the text will be posted on your timeline.

If you add a file name with the command, The client will post its content. You can specify '`-`' to the position and it means that the command read the text to post from *standard input*; it will be helpful for running your own Twitter bot account.

    $ echo Hello world | tf create -

The command prints a tweet ID of the posted tweet if it successfully posted.

### `tf delete`

    $ tf delete tweet_id

The command delete the tweet having given _tweet_id_. Naturally, the tweet should be posted by your account.

### `tf version`

    $ tf version

It shows the version of the package and exit.

## License

The MIT license. See `LICENSE`.

## Road map

My main motivation for the project is re-inventing a solution for running Twitter bot. Therefore, the priority for further implementation will be something related to posting (e.g. attaching images etc.) and features of getting information will be less supplied. However, you will find easily how to expand the feature when you watch the source code of the project. It is always free to do so, and pull requests are always welcome.