Skip to content

Lantern makes it incredibly easy to reveal your live Discord status through a RESTful API and WebSocket connection in under 10 seconds.

License

Notifications You must be signed in to change notification settings

discordplace/lantern

Repository files navigation

🔦 Lantern: Illuminate Your Discord Presence with Real-Time API and WebSocket

Lantern is a powerful service designed to effortlessly broadcast your active Discord status to both a RESTful API endpoint (lantern.rest/api/v1/users/:your_id) and a WebSocket connection. Want to showcase your current Spotify tracks on your personal site? Lantern has you covered.

While Lantern is ready to use out-of-the-box without the need for any deployment, it also offers the flexibility for self-hosting with minimal setup. Enjoy seamless integration and real-time updates with Lantern.


Table of Contents


API Docs

Lantern provides OpenAPI documentation for the RESTful API, which you can access at https://lantern.rest/docs. The API offers endpoints to retrieve user data and key-value storage.

You can also refer to the swagger.json file in the repository for the API documentation. The API endpoints are as follows:

GET /api/v1/users

Retrieve the data of users with the specified IDs.

Parameters
Name Type Description
user_ids string The IDs of the users to retrieve.

Note

  • The user_ids parameter should be an array of user IDs. You should include this parameter multiple times for each user ID you want to retrieve.
  • The maximum number of user IDs you can retrieve at once is 50.
  • Example: ?user_ids=123456789012345678&user_ids=234567890123456789
Response
Example Response
[
  {
    // User metadata object
    "metadata": {
      "id": "123456789012345678",
      "username": "example",
      "discriminator": "0",
      "global_name": "example",
      "avatar": "abcdef1234567890",
      "avatar_url": "https://cdn.discordapp.com/avatars/123456789012345678/123456789012345678.png",
      "display_avatar_url": "https://cdn.discordapp.com/avatars/123456789012345678/123456789012345678.png",
      "bot": false,
      "flags": {
        "human_readable": ["Staff"],
        "bitfield": 1
      },
      "monitoring_since": {
        "unix": 1620000000,
        "raw": "2021-05-03T00:00:00.000Z"
      }
    },
    "status": "online",
    // Active platforms object with current Spotify track
    "active_platforms": {
      "desktop": "online",
      "mobile": "offline",
      "web": "offline",
      "spotify": {
        "track_id": "abcdef1234567890",
        "song": "example",
        "artist": "example",
        "album": "example",
        "album_cover": "https://i.scdn.co/image/abcdef1234567890",
        "start_time": {
          "unix": 1620000000,
          "raw": "2021-05-03T00:00:00.000Z"
        },
        "end_time": {
          "unix": 1620000000,
          "raw": "2021-05-03T00:00:00.000Z"
        },
        "time": {
          "current_human_readable": "00:00",
          "end_human_readable": "00:00"
        }
      }
    },
    // Array of user activities
    "activities": [
      {
        "id": "abcdef1234567890",
        "name": "example",
        "type": "PLAYING",
        "state": "example",
        "details": "example",
        "application_id": "123456789012345678",
        "created_at": 1620000000,
        "assets": {
          "large_image": {
            "hash": "abcdef1234567890",
            "image_url": "https://cdn.discordapp.com/app-assets/123456789012345678/abcdef1234567890.png",
            "text": "example"
          },
          "small_image": {
            "hash": "abcdef1234567890",
            "image_url": "https://cdn.discordapp.com/app-assets/123456789012345678/abcdef1234567890.png",
            "text": "example"
          }
        },
        "timestamps": {
          "start_time": {
            "unix": 1620000000,
            "raw": "2021-05-03T00:00:00.000Z"
          }
        }
      }
    ],
    // Key-value pairs for the user (if any)
    "storage": {
      "key": "value"
    }
  },
  // Additional user objects
]
GET /api/v1/users/:id

Retrieve the data of a user with the specified ID.

Parameters
Name Type Description
id string The ID of the user to retrieve.
svg boolean Whether to return the user's avatar as an SVG image. Defaults to false.
theme string The theme to use for the user's card. Must be either light or dark.
borderRadius number The border radius rem value for the user's card. Defaults to 2.
hideGlobalName number Whether to hide the user's global name. Must be either 0 or 1.
hideStatus number Whether to hide the user's status. Must be either 0 or 1.
hideBadges number Whether to hide the user's badges. Must be either 0 or 1.
hideActivity number Whether to hide the user's activity. Must be either 0 or 1.
noActivityTitle string The title to display when the user has no activity. Default might be No Activity. Can't be greater than 64 characters.
noActivityMessage string The message to display when the user has no activity. Default might be This user is not currently doing anything.. Can't be greater than 256 characters.
Response
Example Response
{
  // User metadata object
  "metadata": {
    "id": "123456789012345678",
    "username": "example",
    "discriminator": "0",
    "global_name": "example",
    "avatar": "abcdef1234567890",
    "avatar_url": "https://cdn.discordapp.com/avatars/123456789012345678/123456789012345678.png",
    "display_avatar_url": "https://cdn.discordapp.com/avatars/123456789012345678/123456789012345678.png",
    "bot": false,
    "flags": {
      "human_readable": ["Staff"],
      "bitfield": 1
    },
    "monitoring_since": {
      "unix": 1620000000,
      "raw": "2021-05-03T00:00:00.000Z"
    }
  },
  "status": "online",
  // Active platforms object with current Spotify track
  "active_platforms": {
    "desktop": "online",
    "mobile": "offline",
    "web": "offline",
    "spotify": {
      "track_id": "abcdef1234567890",
      "song": "example",
      "artist": "example",
      "album": "example",
      "album_cover": "https://i.scdn.co/image/abcdef1234567890",
      "start_time": {
        "unix": 1620000000,
        "raw": "2021-05-03T00:00:00.000Z"
      },
      "end_time": {
        "unix": 1620000000,
        "raw": "2021-05-03T00:00:00.000Z"
      },
      "time": {
        "current_human_readable": "00:00",
        "end_human_readable": "00:00"
      }
    }
  },
  // Array of user activities
  "activities": [
    {
      "id": "abcdef1234567890",
      "name": "example",
      "type": "PLAYING",
      "state": "example",
      "details": "example",
      "application_id": "123456789012345678",
      "created_at": 1620000000,
      "assets": {
        "large_image": {
          "hash": "abcdef1234567890",
          "image_url": "https://cdn.discordapp.com/app-assets/123456789012345678/abcdef1234567890.png",
          "text": "example"
        },
        "small_image": {
          "hash": "abcdef1234567890",
          "image_url": "https://cdn.discordapp.com/app-assets/123456789012345678/abcdef1234567890.png",
          "text": "example"
        }
      },
      "timestamps": {
        "start_time": {
          "unix": 1620000000,
          "raw": "2021-05-03T00:00:00.000Z"
        }
      }
    }
  ],
  // Key-value pairs for the user (if any)
  "storage": {
    "key": "value"
  }
}

WebSocket

The WebSocket connection is available at wss://lantern.rest/socket.

Once connected, you will receive Opcode 1: Hello which will contain heartbeat_interval in the data field.

You should set a repeating interval for the time specified in heartbeat_interval which should send Opcode 4: Heartbeat on the interval.

You should send Opcode 2: Initialize immediately after receiving Opcode 1: Hello with the following payload:

Subscribe to User
{
  "op": 2,
  "d": {
    "user_id": "123456789012345678"
  }
}
Subscribe to Multiple Users
{
  "op": 2,
  "d": {
    "user_ids": ["123456789012345678", "234567890123456789"]
  }
}
Subscribe to All Users
{
  "op": 2,
  "d": {
    "user_id": "All"
  }
}

You will receive Opcode 3: Initialize Acknowledgement once the server has acknowledged your subscription and this will contain the all data for the user(s) you have subscribed to in the d field.

If any user you have subscribed to updates their presence, you will receive Opcode 6: Presence Update with the updated data in the d field.

If any user you have subscribed leaves the Lantern server, you will receive Opcode 7: User Left with the user ID in the d field. (when subscribing to multiple users, you will receive this for each user that leaves, if no users are left, you will receive Opcode 9: Disconnect)

Additionally, if you want to add or remove a user from your subscription, you can also send Opcode 12: Subscribe and Opcode 14: Unsubscribe respectively. Note that, if you remove all users from your subscription, you will receive Opcode 9: Disconnect.

List of Opcodes
Opcode Description Type
1 HELLO Server -> Client
2 INIT Client -> Server
3 INIT_ACK Server -> Client
4 HEARTBEAT Client -> Server
5 HEARTBEAT_ACK Server -> Client
6 PRESENCE_UPDATE Server -> Client
7 USER_LEFT Server -> Client
8 USER_JOINED Server -> Client
9 DISCONNECT Server -> Client
10 STORAGE_UPDATE Server -> Client
11 ERROR Server -> Client
12 SUBSCRIBE Client -> Server
13 SUBSCRIBE_ACK Server -> Client
14 UNSUBSCRIBE Client -> Server
15 UNSUBSCRIBE_ACK Server -> Client
Example Payloads
Opcode 1: Hello
{
  "t": "HELLO",
  "op": 1,
  "d": {
    "heartbeat_interval": 10000
  }
}
Opcode 2: Initialize
{
  "op": 2,
  "d": {
    "user_id": "123456789012345678"
  }
}
Opcode 3: Initialize Acknowledgement
{
  "t": "INIT_ACK",
  "op": 3,
  "d": {
    // User data
    // Can be array if multiple users are subscribed
  }
}
Opcode 4: Heartbeat
{
  "t": "HEARTBEAT",
  "op": 4
}
Opcode 5: Heartbeat Acknowledgement
{
  "t": "HEARTBEAT_ACK",
  "op": 5
}
Opcode 6: Presence Update
{
  "t": "PRESENCE_UPDATE",
  "op": 6,
  "d": {
    // Updated user data
    // Can be array if multiple users are subscribed
  }
}
Opcode 7: User Left
{
  "t": "USER_LEFT",
  "op": 7,
  "d": {
    "user_id": "123456789012345678"
  }
}
Opcode 8: User Joined
{
  "t": "USER_JOINED",
  "op": 8,
  "d": {
    // User data
  }
}
Opcode 9: Disconnect
{
  "t": "DISCONNECT",
  "op": 9,
  "d": {
    "reason": "Connection timed out."
  }
}
Opcode 10: Storage Update
{
  "t": "STORAGE_UPDATE",
  "op": 10,
  "d": {
    // All key-value pairs for the user
    "key": "value"
  }
}
Opcode 11: Error
{
  "t": "ERROR",
  "op": 11,
  "d": "Something went wrong."
}
Opcode 12: Subscribe
{
  "op": 12,
  "d": {
    "user_id": "123456789012345678"
  }
}
{
  "op": 12,
  "d": {
    "user_ids": ["123456789012345678", "234567890123456789"]
  }
}
{
  "op": 12,
  "d": {
    "user_id": "All"
  }
}
Opcode 13: Subscribe Acknowledgement
{
  "t": "SUBSCRIBE_ACK",
  "op": 13
}
Opcode 14: Unsubscribe
{
  "op": 14,
  "d": {
    "user_id": "123456789012345678"
  }
}
{
  "op": 14,
  "d": {
    "user_ids": ["123456789012345678", "234567890123456789"]
  }
}
{
  "op": 14,
  "d": {
    "user_id": "All"
  }
}
Opcode 15: Unsubscribe Acknowledgement
{
  "t": "UNSUBSCRIBE_ACK",
  "op": 15
}

KV Storage

Lantern also offers a simple key-value storage system that can be accessed through the RESTful API, WebSocket or the Lantern bot itself.

Use cases

  • Configuration values for your website
  • Dynamic data for your website/profile (e.g. current location)
  • User-specific data (e.g. user preferences)
  • Temporary data storage

Limits

  1. Keys and values can only be strings (You can store JSON objects as strings)
  2. Values can be 30,000 characters maximum
  3. Keys must be alphanumeric (a-Z, A-Z, 0-9) and 255 characters max length
  4. You can only store up to 512 key-value pairs linked

WebSocket

You can access the KV storage through the WebSocket connection. The following opcodes are available for the KV storage:

Opcode 10: Storage Update

This opcode is sent when a key-value pair is created, updated or deleted.

Payload
{
  "t": "STORAGE_UPDATE",
  "op": 10,
  "d": {
    // All key-value pairs for the user
    "key": "value"
  }
}

RESTful API

For requests to the KV storage API, you will need to include the Authorization header with the value you get from the Lantern bot (use /storage create token command). The bot will provide you with a unique token that you can use to access the KV storage.

Without the Authorization header, you can only access the data you have stored with the bot itself.

GET /api/v1/users/:user_id/storage

Retrieve all key-value pairs for a specific user.

Parameters
Name Type Description
user_id string The ID of the user to retrieve the key-value pairs from.
Response
Example Response
{
  "key1": "value1",
  "key2": "value2"
}
DELETE /api/v1/users/:user_id/storage (Requires Authorization header)

Delete all key-value pairs for a specific user.

Parameters
Name Type Description
user_id string The ID of the user to delete the key-value pairs from.
Response
Example Response
{
  "success": true
}
GET /api/v1/users/:user_id/storage/:key

Retrieve the value of a key for a specific user.

Parameters
Name Type Description
user_id string The ID of the user to retrieve the key from.
key string The key to retrieve the value for.
Response
Example Response
{
  "value": "example_value"
}
PUT /api/v1/users/:user_id/storage/:key (Requires Authorization header)

Create a new key-value pair for a specific user.

Parameters
Name Type Description
user_id string The ID of the user to create the key-value pair for.
key string The key to create.
value string The value to assign to the key.
Response
Example Response
{
  "success": true
}
PATCH /api/v1/users/:user_id/storage/:key (Requires Authorization header)

Update the value of a key for a specific user.

Parameters
Name Type Description
user_id string The ID of the user to update the key-value pair for.
key string The key to update.
value string The new value to assign to the key.
Response
Example Response
{
  "success": true
}
DELETE /api/v1/users/:user_id/storage/:key (Requires Authorization header)

Delete a key-value pair for a specific user.

Parameters
Name Type Description
user_id string The ID of the user to delete the key-value pair from.
key string The key to delete.
Response
Example Response
{
  "success": true
}

Self-Hosting

To self-host Lantern, you will need to have the following prerequisites installed on your system:

Once you have the prerequisites installed, follow these steps to self-host Lantern:

  1. Clone the repository to your local machine:
git clone https://github.com/discordplace/lantern.git
  1. Navigate to the cloned repository:
cd lantern
  1. Install the required dependencies:
pnpm install
  1. Rename the .env.example file to .env and fill in the configuration values:
DISCORD_BOT_TOKEN=your_discord_bot_token
MONGODB_URI=your_mongodb_uri
MONGODB_NAME=your_mongodb_name
KV_TOKEN_ENCRYPTION_SECRET=your_256_bit_encryption_secret

Note

  • KV_TOKEN_ENCRYPTION_SECRET should be a 256-bit encryption secret that you generate. You can use a tool like this. This secret is used to encrypt the KV storage token. So make sure to keep it secure.
  1. Fill these configuration values in the config.toml file with your own values:
base_guild_id = 'your_base_guild_id'

[server]
port = 8000
  1. Start the server. This builds the app and starts the server:
pnpm start
  1. The server should now be running on http://localhost:8000. You can access the API from this URL. The WebSocket connection is available at ws://localhost:8000/socket.

  2. (Optional) To register/unregister bot commands, run the following command:

npm run bot:registerCommands
npm run bot:unregisterCommands

Note

Make sure you enable these settings in your bot's application settings:

  • PRESENCE INTENT
  • GUILD MEMBERS INTENT

Contributing

We welcome contributions from the community! If you'd like to contribute to the project, please follow these guidelines:

  1. Fork the repository and clone it locally.
  2. Create a new branch for your feature or bug fix.
  3. Make your changes and ensure the code passes any existing tests.
  4. Commit your changes with descriptive commit messages that follow the Conventional Commits standard.
  5. Push your changes to your fork and submit a pull request to the main branch of the original repository.

Please make sure to follow the Code of Conduct and Contributing Guidelines when contributing to this project.

Help

If you encounter any issues with the Lantern or have any questions, feel free to open an issue on this repository. We'll do our best to assist you!

License

This project is licensed under The GNU General Public License v3.0.

About

Lantern makes it incredibly easy to reveal your live Discord status through a RESTful API and WebSocket connection in under 10 seconds.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Sponsor this project

 

Contributors 3

  •  
  •  
  •