Git Product home page Git Product logo

lanyard's Introduction

Lanyard Logo

๐Ÿท๏ธ Expose your Discord presence and activities to a RESTful API and WebSocket in less than 10 seconds

Lanyard is a service that makes it super easy to export your live Discord presence to an API endpoint (api.lanyard.rest/v1/users/:your_id) and to a WebSocket (see below) for you to use wherever you want - for example, I use this to display what I'm listening to on Spotify on my personal website. It also acts as a globally-accessible realtime KV store which you can update from the Lanyard Discord bot or from the Lanyard API.

You can use Lanyard's API without deploying anything yourself - but if you want to self host it, you have the option to, though it'll require a tiny bit of configuration.

Get started in < 10 seconds

Just join this Discord server and your presence will start showing up when you GET api.lanyard.rest/v1/users/:your_id. It's that easy.

Table of Contents

Community Projects

The Lanyard community has worked on some pretty cool projects that allows you to extend the functionality of Lanyard. PR to add a project!

lanyard-web - Landing page and API documentation concept for Lanyard API with a sleek UI.
lanyard-profile-readme - Utilize Lanyard to display your Discord Presence in your GitHub Profile
vue-lanyard - Lanyard API plugin for Vue. Supports REST and WebSocket methods
react-use-lanyard - React hook for Lanyard - supports REST & WebSocket
use-lanyard - Another React hook for Lanyard that uses SWR
lanyard-visualizer - Beautifully display your Discord presence on a website
hawser - Lanyard API wrapper for python. Supports both REST and WebSocket.
js-lanyard - Use Lanyard in your Web App.
go-lanyard - Lanyard API wrapper for GoLang - supports REST & WebSocket
use-lanyard - Lanyard with Composition API for Vue. Supports REST and WebSocket methods
use-listen-along - Mock the discord 'Listen Along' feature within a react hook powered by the Lanyard API.
lanyard-graphql - A GraphQL port of the Lanyard API.
sk-lanyard - SvelteKit integration with Lanyard, supports REST & WebSocket.
svelte-lanyard - A Lanyard API wrapper for Svelte. Supports REST & WebSocket.
denyard - Lanyard API wrapper for Deno - Supports REST & WebSocket.
lanyard-ui - Lanyard visualizer focused on the KV aspect
discord-status-actions - Updates a file to include your discord status using the Lanyard API.
discordstatus-website - Display your Discord status on your own website with premade CSS, and JS
osu-nowplaying - A small tool to scrape the info of the map you're curently playing on osu!lazer and dump into a file for obs to read.
lanyard.py - An asynchronous implementation of the Lanyard websocket and HTTP for python

API Docs

Getting a user's presence data

GET https://api.lanyard.rest/v1/users/:user_id

Example response:

{
  "success": true,
  "data": {
    "active_on_discord_mobile": false,
    "active_on_discord_desktop": true,
    "listening_to_spotify": true,
    // Lanyard KV
    "kv": {
      "location": "Los Angeles, CA"
    },
    // Below is a custom crafted "spotify" object, which will be null if listening_to_spotify is false
    "spotify": {
      "track_id": "3kdlVcMVsSkbsUy8eQcBjI",
      "timestamps": {
        "start": 1615529820677,
        "end": 1615530068733
      },
      "song": "Let Go",
      "artist": "Ark Patrol; Veronika Redd",
      "album_art_url": "https://i.scdn.co/image/ab67616d0000b27364840995fe43bb2ec73a241d",
      "album": "Let Go"
    },
    "discord_user": {
      "username": "Phineas",
      "public_flags": 131584,
      "id": "94490510688792576",
      "discriminator": "0001",
      "avatar": "a_7484f82375f47a487f41650f36d30318"
    },
    "discord_status": "online",
    // activities contains the plain Discord activities array that gets sent down with presences
    "activities": [
      {
        "type": 2,
        "timestamps": {
          "start": 1615529820677,
          "end": 1615530068733
        },
        "sync_id": "3kdlVcMVsSkbsUy8eQcBjI",
        "state": "Ark Patrol; Veronika Redd",
        "session_id": "140ecdfb976bdbf29d4452d492e551c7",
        "party": {
          "id": "spotify:94490510688792576"
        },
        "name": "Spotify",
        "id": "spotify:1",
        "flags": 48,
        "details": "Let Go",
        "created_at": 1615529838051,
        "assets": {
          "large_text": "Let Go",
          "large_image": "spotify:ab67616d0000b27364840995fe43bb2ec73a241d"
        }
      },
      {
        "type": 0,
        "timestamps": {
          "start": 1615438153941
        },
        "state": "Workspace: lanyard",
        "name": "Visual Studio Code",
        "id": "66b84f5317e9de6c",
        "details": "Editing README.md",
        "created_at": 1615529838050,
        "assets": {
          "small_text": "Visual Studio Code",
          "small_image": "565945770067623946",
          "large_text": "Editing a MARKDOWN file",
          "large_image": "565945077491433494"
        },
        "application_id": "383226320970055681"
      }
    ]
  }
}

KV

Lanyard KV is a a dynamic, real-time key->value store which is added to the Lanyard user API response. When a KV pair is updated, a PRESENCE_UPDATE for the user will also be emitted through the Lanyard socket.

Use cases

  • Configuration values for your website
  • Configuration values for Lanyard 3rd party projects
  • Dynamic data for your website/profile (e.g. current location)

Limits

  1. Keys and values can only be strings
  2. Values can be 30,000 characters maximum
  3. Keys must be alphanumeric (a-zA-Z0-9) and 255 characters max length
  4. Your user can have a maximum of 512 key->value pairs linked

Getting an API Key

DM the Lanyard bot (Lanyard#5766) with .apikey to get your API key.

When making Lanyard KV API requests, set an Authorization header with the API key you received from the Lanyard bot as the value.

Setting a key->value pair

Discord

.set <key> <value>

HTTP

PUT https://api.lanyard.rest/v1/users/:user_id/kv/:key The value will be set to the body of the request. The body can be any type of data, but it will be string-encoded when set in Lanyard KV.

Setting multiple key->value pairs

Discord

Not yet implemented

HTTP

PATCH https://api.lanyard.rest/v1/users/:user_id/kv The user's KV store will be merged with the body of the request. Conflicting keys will be overwritten. The body must be keyvalue pair object with a maximum depth of 1.

Deleting a key

Discord

.del <key>

HTTP

DELETE https://api.lanyard.rest/v1/users/:user_id/kv/:key

Socket Docs

The websocket is available at wss://api.lanyard.rest/socket. If you would like to use compression, please specify ?compression=zlib_json at the end of the URL.

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 3: Heartbeat on the interval.

You should send Opcode 2: Initialize immediately after receiving Opcode 1.

Example of Opcode 2: Initialize:

{
  op: 2,
  d: {
    // subscribe_to_ids should be an array of user IDs you want to subscribe to presences from
    // if Lanyard doesn't monitor an ID specified, it won't be included in INIT_STATE
    subscribe_to_ids: ["94490510688792576"]
  }
}

Subscribing to multiple user presences

To subscribe to multiple presences, send subscribe_to_ids in the data object with a string[] list of user IDs to subscribe to. Then, INIT_STATE's data object will contain a user_id->presence map. You can find examples below.

Subscribing to a single user presence

If you just want to subscribe to one user, you can send subscribe_to_id instead with a string of a single user ID to subscribe to. Then, the INIT_STATE's data will just contain the presence object for the user you've subscribed to instead of a user_id->presence map.

Subscribing to every user presence

If you want to subscribe to every presence being monitored by Lanyard, you can specify subscribe_to_all with (bool) true in the data object, and you will then receive a user_id->presence map with every user presence in INIT_STATE, and their respective PRESENCE_UPDATES when they happen.

Once Op 2 is sent, you should immediately receive an INIT_STATE event payload if connected successfully. If not, you will be disconnected with an error (see below).

List of Opcodes

Opcode Name Description Client Send/Recv
0 Event This is the default opcode when receiving core events from Lanyard, like INIT_STATE Receive
1 Hello Lanyard sends this when clients initially connect, and it includes the heartbeat interval Receive Only
2 Initialize This is what the client sends when receiving Opcode 1 from Lanyard - it should contain an array of user IDs to subscribe to Send only
3 Heartbeat Clients should send Opcode 3 every 30 seconds (or whatever the Hello Opcode says to heartbeat at) Send only

Events

Events are received on Opcode 0: Event - the event type will be part of the root message object under the t key.

Example Event Message Objects

INIT_STATE

{
  op: 0,
  seq: 1,
  t: "INIT_STATE",
  d: {
    "94490510688792576": {
      // Full Lanyard presence (see API docs above for example)
    }
  }
}

PRESENCE_UPDATE

{
  op: 0,
  seq: 2,
  t: "PRESENCE_UPDATE",
  d: {
    // Full Lanyard presence and an extra "user_id" field
  }
}

Error Codes

Lanyard can disconnect clients for multiple reasons, usually to do with messages being badly formatted. Please refer to your WebSocket client to see how you should handle errors - they do not get received as regular messages.

Types of Errors

Name Code Data
Invalid/Unknown Opcode 4004 unknown_opcode
Opcode Requires Data 4005 requires_data_object
Invalid Payload 4006 invalid_payload

Quicklinks

Lanyard quicklinks allow you to easily access resources from Discord, such as profile pictures.

User Icons

https://api.lanyard.rest/<id>.<file_type> Where id is the Discord user ID. file_type can be one of: png, gif, webp, jpg, or jpeg

Self-host with Docker

Build the Docker image by cloning this repo and running:

# The latest version is already on the docker hub, you can skip this step unless you would like to run a modified version.
docker build -t phineas/lanyard:latest .

If you don't already have a redis server you'll need to run one, here's the docker command to run one:

docker run -d --name lanyard-redis -v docker_mount_location_on_host:/data redis

And run Lanyard API server using:

docker run --rm -it -p 4001:4001 -e REDIS_HOST=redis -e BOT_TOKEN=<token> --link lanyard-redis:redis phineas/lanyard:latest

You'll be able to access the API using port 4001.

You also need to create a Discord bot and use its token above.

Create a bot here: https://discord.com/developers/applications

Make sure you enable these settings in your bot settings:

  • Privileged Gateway Intents > PRESENCE INTENT
  • Privileged Gateway Intents > SERVER MEMBERS INTENT

If you'd like to run Lanyard with docker-compose, here's an example:

version: "3.8"

services:
  redis:
    image: redis
    restart: always
    container_name: lanyard_redis
  lanyard:
    image: phineas/lanyard:latest
    restart: always
    container_name: lanyard
    depends_on:
      - redis
    ports:
      - 4001:4001
    environment:
      BOT_TOKEN: <token>
      REDIS_HOST: redis

Note, that you're hosting a http server, not https. You'll need to use a reverse proxy such as traefik if you want to secure your API endpoint.

Showcase

Below is a curated selection of websites using Lanyard right now, check them out! Some of them will only show an activity when they're active.

lanyard's People

Contributors

amineohn avatar ardasoyturk avatar barbarbar338 avatar cancodes avatar chezzzer avatar d3r1n avatar discordanaxes avatar dustinrouillard avatar eggsy avatar elevenski avatar emirkabal avatar encrypteddev avatar geenva avatar heyimnitho avatar itzpolah avatar leonardssh avatar loom4k avatar makidoll avatar malloryhayr avatar mehmetali345dev avatar meppu avatar nebulatgs avatar officialcrugg avatar pateln123 avatar phineas avatar punctuations avatar pxseu avatar robjmorrissey avatar sayanzyx avatar vopswtf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lanyard's Issues

Last seen feature

Adding last_seen timestamp when user is offline/invisible might be useful since it can tell when the last time user is active.

Discord Bio & Banner?

Hey there,
would it be possible to also put a user's bio and their banner on the User Endpoint?

Discord Bots?

Make it so that we can invite bots to the lanyard server (without permissions ofc) so that we can see if our bots is online or not

Error in Self Hosting

{"success":false,"error":{"message":"User is not being monitored by Lanyard","code":"user_not_monitored"}}

New username system

Hello, as you have probably seen already, usernames are evolving on discord. Therefore, the old way of displaying the tag will become obsolete (see image).

Are there any update planned to evolve according to these changes ?

I'm also mentionning that a new badge has also appeared in relation to these changes so maybe it could be added as well.

image

Missing info at example response: spotify track id

Real Response:

"spotify": {
            "track_id": "3iag81mU7BylirRwRYXd8E",
            "timestamps": {
                "start": 1628585067370,
                "end": 1628585292130
            },
            "song": "I'm Only Joking",
            "artist": "KONGOS",
            "album_art_url": "https://i.scdn.co/image/ab67616d0000b27367ff87e2839c5c93bb6e6a6a",
            "album": "Lunatic"
},

the one in the readme:

"spotify": {
      "timestamps": {
        "start": 1615529820677,
        "end": 1615530068733
      },
      "song": "Let Go",
      "artist": "Ark Patrol; Veronika Redd",
      "album_art_url": "https://i.scdn.co/image/ab67616d0000b27364840995fe43bb2ec73a241d",
      "album": "Let Go"
},

Lanyard API not working

On my Website avyanshralph.vercel.app The Discord Activity status is not showing when hosted on vercel but it shows when I host it locally... Pls tell the reason behind this issue

Regards,
Avyansh Ralph
Owner of Airdown

Needed help.

Hello!

Basically I have some problems with my website.
At first, timestamps are not working correctly.
image
And second. Song/video doesnt update some times
image
And finally. When presence doesnt have timestamp, console goes crazy.
image

Suggestion: Custom CORS Header?

Now, Every website can access our Discord status with the lanyard API but with custom CORS (cross-origin resource sharing) headers we can set what websites can access our status.

Discord Status

So im having an issue with the "discord_status":"..." not showing up correctly and I have as my snippet:

				{#if userPresence.discord_status === 'offline'}
					<br />
					Offline
				{:else}
					<div
						class="inline-block text-sm drop-shadow-3xl shadow-orange-300/50 bg-gradient-to-r from-blue-500/[.15] ring-2 ring-orange-800/95 rounded-md p-3 -ml-6"
					>
						{#if userPresence.discord_status === 'idle'}
							๐ŸŸก Idle&nbsp;&nbsp;
						{:else if userPresence.discord_status === 'dnd'}
							๐ŸŸ  Do Not Disturb&nbsp;&nbsp;
						{:else}
							๐ŸŸข Online&nbsp;
						{/if} 

and my <script></script> is:

	// check if the user is currently in VSCode
	$: inVSCode =
		userPresence?.data?.discord_status == 'dnd' &&
		userPresence?.data?.activities?.find((activity) => activity?.name == 'Visual Studio Code');

	// get the icon to display based on whether the user is listening to Spotify or coding in VSCode
	$: statusIcon = inVSCode ? VSCODE_ICON : currentActivity ? SPOTIFY_ICON : null;

	// check if the user is online or idle
	$: isOnline =
		userPresence?.discord_status === 'online' || userPresence?.discord_status === 'idle';

	// get the details of the user's current VSCode session
	$: vsCodeSession = userPresence?.data?.activities?.find(
		(activity) => activity?.name === 'Visual Studio Code'
	);

	// get the name and ID of the current file being edited
	$: fileName = vsCodeSession?.details?.match(/(?<=๐Ÿ“\s).+(?=\s\|)/)?.[0];
	$: fileId = vsCodeSession?.id;

	// get the line number being edited
	$: lineNum = vsCodeSession?.details?.match(/(?<=๐Ÿ“ Editing line ).+(?=\/)/)?.[0] ?? '';

	// construct the status message to display
	$: statusMessage =
		isOnline && inVSCode && fileName && lineNum
			? `Editing ${fileName} on line ${lineNum} in VSCode`
			: isOnline && currentActivity
			? `Listening to ${currentSong}`
			: 'Offline';
			```
So when I manually change the status to test it, it works via lanyard api and shows the correct status but, it change on my webpage.

Is anyone else having this issue or is it just me?

Time Elapsed?

I'd like to be able to see time elapsed with Lanyard.

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.