├── .gitignore
├── LICENSE
├── README.md
├── demo.png
├── nuxt.config.ts
├── package.json
├── pnpm-lock.yaml
├── src
├── app.vue
├── app
│ └── router.options.ts
├── components
│ ├── Button.vue
│ ├── CLink.vue
│ ├── Card
│ │ └── CommunityProject.vue
│ ├── FloatingButton.vue
│ ├── Footer.vue
│ ├── GradientBackground.vue
│ ├── Highlight.vue
│ ├── Loader.vue
│ ├── Navbar.vue
│ ├── Stargazers.vue
│ └── content
│ │ ├── ErrorTypes.vue
│ │ ├── IntroductionResponse.vue
│ │ ├── ListOpcodes.vue
│ │ ├── NotFound.vue
│ │ └── Pages.vue
├── composables
│ └── useReadmeProjects.ts
├── content
│ └── api
│ │ ├── getting-user-presence.md
│ │ ├── introduction.md
│ │ ├── kv.md
│ │ ├── quicklinks.md
│ │ ├── self-hosting.md
│ │ └── working-with-websockets.md
├── data
│ ├── communityProjects.ts
│ └── usedBy.ts
├── pages
│ ├── api
│ │ └── [...slug].vue
│ └── index.vue
└── public
│ ├── icon.png
│ └── social-image.png
├── tailwind.config.js
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log*
3 | .nuxt
4 | .nitro
5 | .cache
6 | .output
7 | .env
8 | dist
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Abdulbaki "EGGSY" Dursun
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Lanyard Website
2 |
3 | [✨ Go to Lanyard's repository](https://github.com/phineas/lanyard)
4 |
5 |
6 |
7 |
8 |
9 | A new, beautiful and the-way-it-supposed-to-be way to review Lanyard, its community projects, websites that use Lanyard and the API Documentation in one place!
10 |
11 | Built with [Nuxt 3](https://v3.nuxtjs.org), [Tailwind CSS](https://tailwindcss.com) and [VueUse](https://vueuse.org)
12 |
13 | ## Add Your Website
14 |
15 | To add your own website or project to show it off on here, you should go to the [main repository of Lanyard](https://github.com/phineas/lanyard) and follow the instructions there; this website parses that repository's readme file and updates itself automatically.
16 |
17 | ### Sponsors
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | ### License
26 |
27 | [MIT License](https://github.com/eggsy/lanyard-web/blob/main/LICENSE) © Abdulbaki "EGGSY" Dursun
28 |
--------------------------------------------------------------------------------
/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eggsy/lanyard-web/285050628a36b52c1eb8f9f3b6192e102bce001b/demo.png
--------------------------------------------------------------------------------
/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | // https://v3.nuxtjs.org/api/configuration/nuxt.config
2 | export default defineNuxtConfig({
3 | compatibilityDate: "2024-08-12",
4 |
5 | rootDir: ".",
6 | srcDir: "./src",
7 | components: true,
8 |
9 | modules: [
10 | "@nuxtjs/tailwindcss",
11 | "@nuxt/content",
12 | "@vueuse/motion/nuxt",
13 | "@nuxt/icon",
14 | ],
15 |
16 | content: {
17 | highlight: {
18 | theme: "one-dark-pro",
19 | },
20 | },
21 |
22 | runtimeConfig: {
23 | public: {
24 | DISCORD: "https://discord.gg/UrXF2cfJ7F",
25 | API_BASE: "https://api.lanyard.rest/v1/users",
26 | GITHUB_REPO: "https://github.com/eggsy/lanyard-web",
27 | },
28 | },
29 |
30 | tailwindcss: {
31 | viewer: false,
32 | },
33 | });
34 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "build": "nuxt build",
5 | "dev": "nuxt dev",
6 | "generate": "nuxt generate",
7 | "preview": "nuxt preview"
8 | },
9 | "devDependencies": {
10 | "@nuxt/content": "^2.13.2",
11 | "@nuxt/icon": "^1.4.5",
12 | "@tailwindcss/typography": "^0.5.14",
13 | "@types/prismjs": "^1.26.4",
14 | "nuxt": "^3.12.4",
15 | "sass": "^1.77.8"
16 | },
17 | "dependencies": {
18 | "@nuxtjs/tailwindcss": "^6.12.1",
19 | "@vueuse/motion": "2.0.0-beta.18",
20 | "@vueuse/shared": "^10.11.1",
21 | "ipx": "^3.0.1",
22 | "shiki": "^1.12.1"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/app.vue:
--------------------------------------------------------------------------------
1 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
121 |
--------------------------------------------------------------------------------
/src/app/router.options.ts:
--------------------------------------------------------------------------------
1 | import type { RouterConfig } from "@nuxt/schema";
2 |
3 | export default {
4 | scrollBehavior() {
5 | window?.scrollTo(0, 0);
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/src/components/Button.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
25 |
26 | {{ label }}
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/components/CLink.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/components/Card/CommunityProject.vue:
--------------------------------------------------------------------------------
1 |
24 |
25 |
26 |
29 |
30 |
36 |
43 |
((e.target as HTMLImageElement).src = '/icon.png')"
49 | />
50 |
51 |
57 | {{ getNameSegments.owner }}
58 |
59 |
60 |
61 |
62 | /
63 |
64 |
65 |
66 | {{ getNameSegments.repo }}
67 |
68 |
69 |
70 | {{ description }}
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/src/components/FloatingButton.vue:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
27 |
28 |
29 |
30 |
45 |
--------------------------------------------------------------------------------
/src/components/Footer.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
11 |
12 |
13 |
14 | Lanyard by
15 | @phineas ,
16 | website by
17 | @eggsy
18 |
19 |
20 | This website is open source on GitHub
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/components/GradientBackground.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
--------------------------------------------------------------------------------
/src/components/Highlight.vue:
--------------------------------------------------------------------------------
1 |
26 |
27 |
28 |
32 |
33 |
34 |
51 |
--------------------------------------------------------------------------------
/src/components/Loader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
14 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/components/Navbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
14 |
15 |
16 |
17 | Home
18 |
19 |
20 |
21 |
22 | API
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/components/Stargazers.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 |
Stargazers
25 |
26 |
33 |
34 | Star on GitHub
35 |
36 |
37 |
38 |
39 |
40 | An error occured.
41 |
42 |
43 |
52 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/components/content/ErrorTypes.vue:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
28 |
29 |
30 | {{ item.code }}
31 |
32 |
33 |
{{ item.name }}
34 |
35 |
36 |
37 | {{ item.data }}
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/components/content/IntroductionResponse.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/components/content/ListOpcodes.vue:
--------------------------------------------------------------------------------
1 |
29 |
30 |
31 |
32 |
36 |
37 |
38 |
41 | {{ index }}
42 |
43 |
44 |
{{ code.name }}
45 |
46 |
47 |
48 | {{ code.type }}
49 |
50 |
51 |
52 |
{{ code.description }}
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/components/content/NotFound.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Not Found
15 |
16 |
17 |
18 | The document you're looking for doesn't exist, check whether you made a
19 | typo or it exists.
20 |
21 | Click here to go back to documentation homepage .
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/components/content/Pages.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
19 |
23 |
24 | {{ article.title }}
25 |
26 |
27 |
28 |
29 | Anan Yani
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/composables/useReadmeProjects.ts:
--------------------------------------------------------------------------------
1 | import { ref, onMounted, reactive } from "vue";
2 |
3 | export const useReadmeProjects = () => {
4 | const loading = ref(true);
5 | const error = ref(false);
6 |
7 | const websites = ref([]);
8 | const projects = ref<{ name: string; href: string; description: string }[]>(
9 | [],
10 | );
11 |
12 | onMounted(async () => {
13 | const readme: { content: string } = await fetch(
14 | "https://api.github.com/repos/phineas/lanyard/readme",
15 | {
16 | headers: {
17 | "User-Agent": "Lanyard Web",
18 | },
19 | },
20 | )
21 | .then((r) => r.json())
22 | .catch(() => {
23 | error.value = true;
24 | loading.value = false;
25 | });
26 |
27 | const text = atob(readme.content).toString();
28 | const regexMatch = /\[(.*?)\]\((.*?)\)/;
29 |
30 | /* Community Projects */
31 | const projectsText = text.split("## Community Projects")[1].split("\n")[2];
32 | const communityProjectsDown = text.split(projectsText)[1];
33 |
34 | console.log(projectsText);
35 |
36 | projects.value = communityProjectsDown
37 | .split("##")[0]
38 | .trim()
39 | .split("\\")
40 | .map((item) => {
41 | const [link, description] = item.replace(/\n/g, "").split(" - ");
42 | const match = link.match(regexMatch) ?? link;
43 |
44 | return {
45 | name: match[1],
46 | href: match[2],
47 | description,
48 | };
49 | });
50 |
51 | const websitesText = text.split("## Showcase")[1].split("\n")[2];
52 | const websitesDown = text?.split(websitesText)?.[1];
53 |
54 | websites.value = websitesDown
55 | .split("##")[0]
56 | .trim()
57 | .split("\n")
58 | .map((item) => {
59 | const match = item.match(regexMatch);
60 | return match?.[1] ?? item;
61 | });
62 |
63 | loading.value = false;
64 | });
65 |
66 | return reactive({
67 | projects,
68 | websites,
69 | loading,
70 | error,
71 | });
72 | };
73 |
--------------------------------------------------------------------------------
/src/content/api/getting-user-presence.md:
--------------------------------------------------------------------------------
1 | ---
2 | head:
3 | meta:
4 | - name: "og:title"
5 | property: "og:title"
6 | content: "Getting User Presence Data"
7 | - name: "twitter:title"
8 | property: "twitter:title"
9 | content: "Getting User Presence Data"
10 |
11 | - name: "description"
12 | property: "description"
13 | content: "Get a user's Discord presence data from REST API via a GET request."
14 | - name: "og:description"
15 | property: "og:description"
16 | content: "Get a user's Discord presence data from REST API via a GET request."
17 | - name: "twitter:description"
18 | property: "twitter:description"
19 | content: "Get a user's Discord presence data from REST API via a GET request."
20 | ---
21 |
22 | # Getting User Presence Data
23 |
24 | Simply send a GET request to users endpoint with your `user ID`. This is for the REST API, if you want to check the WebSocket documentation to get real-time updates, [click here](/api/working-with-websockets).
25 |
26 | ### JavaScript Code
27 |
28 | ```js
29 | fetch("https://api.lanyard.rest/v1/users/162969778699501569")
30 | .then((res) => res.json())
31 | .then(console.log);
32 | ```
33 |
34 | ### Interactive Playground
35 |
36 | `GET https://api.lanyard.rest/v1/users/:user_id`
37 |
38 | ::introduction-response
39 | ::
40 |
--------------------------------------------------------------------------------
/src/content/api/introduction.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | head:
4 | meta:
5 | - name: "og:title"
6 | property: "og:title"
7 | content: "API Introduction"
8 | - name: "twitter:title"
9 | property: "twitter:title"
10 | content: "API Introduction"
11 |
12 | - name: "description"
13 | property: "description"
14 | content: "Learn how you can deal with Lanyard's API using REST and WebSockets."
15 | - name: "og:description"
16 | property: "og:description"
17 | content: "Learn how you can deal with Lanyard's API using REST and WebSockets."
18 | - name: "twitter:description"
19 | property: "twitter:description"
20 | content: "Learn how you can deal with Lanyard's API using REST and WebSockets."
21 | ---
22 |
23 | # Introduction
24 |
25 | Welcome to Lanyard API `v1` documentation. Please keep in mind that this is **_not the official_** documentation for Lanyard. This website (as a whole) was created because Lanyard itself didn't had one. Hopefully, this page will be maintained and become the official documentation.
26 |
27 | ## API Base
28 |
29 | Current API base is `https://api.lanyard.rest/v1`.
30 |
31 | ## Choose a Sub-Page
32 |
33 | Please choose a sub-page to see the relevant documentation.
34 |
35 | ::pages
36 | ::
37 |
--------------------------------------------------------------------------------
/src/content/api/kv.md:
--------------------------------------------------------------------------------
1 | ---
2 | head:
3 | meta:
4 | - name: "og:title"
5 | property: "og:title"
6 | content: "Key-Value Store"
7 | - name: "twitter:title"
8 | property: "twitter:title"
9 | content: "Key-Value Store"
10 |
11 | - name: "description"
12 | property: "description"
13 | content: "Use Lanyard KV to display dynamic and real-time updated data through Lanyard API."
14 | - name: "og:description"
15 | property: "og:description"
16 | content: "Use Lanyard KV to display dynamic and real-time updated data through Lanyard API."
17 | - name: "twitter:description"
18 | property: "twitter:description"
19 | content: "Use Lanyard KV to display dynamic and real-time updated data through Lanyard API."
20 | ---
21 |
22 | # Key-Value Store
23 |
24 | 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.
25 |
26 | ### Use Cases
27 |
28 | - Configuration values for your website
29 | - Configuration values for Lanyard 3rd party projects
30 | - Dynamic data for your website/profile (e.g. current location)
31 |
32 | ### Limits
33 |
34 | 1. Keys and values can only be strings
35 | 2. Values can be 30,000 characters maximum
36 | 3. Keys must be alphanumeric (a-zA-Z0-9) and 255 characters max length
37 | 4. Your user can have a maximum of 512 key->value pairs linked
38 |
39 | ### Getting an API Key
40 |
41 | DM the Lanyard bot (`Lanyard#5766`) with `.apikey` to get your API key.
42 |
43 | When making Lanyard KV API requests, set an `Authorization` header with the API key you received from the Lanyard bot as the value.
44 |
45 | ### Setting a key->value pair
46 |
47 | #### Discord
48 |
49 | `.set `{lang=ts}
50 |
51 | #### HTTP
52 |
53 | `PUT https://api.lanyard.rest/v1/users/:user_id/kv/:key`
54 | 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.
55 |
56 | ### Setting multiple key->value pairs
57 |
58 | #### Discord
59 |
60 | Not yet implemented
61 |
62 | #### HTTP
63 |
64 | `PATCH https://api.lanyard.rest/v1/users/:user_id/kv`
65 | 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.
66 |
67 | ### Deleting a key
68 |
69 | #### Discord
70 |
71 | `.del `{lang=ts}
72 |
73 | #### HTTP
74 |
75 | `DELETE https://api.lanyard.rest/v1/users/:user_id/kv/:key`
76 |
--------------------------------------------------------------------------------
/src/content/api/quicklinks.md:
--------------------------------------------------------------------------------
1 | ---
2 | head:
3 | meta:
4 | - name: "og:title"
5 | property: "og:title"
6 | content: "Quicklinks"
7 | - name: "twitter:title"
8 | property: "twitter:title"
9 | content: "Quicklinks"
10 |
11 | - name: "description"
12 | property: "description"
13 | content: "Use Lanyard Quicklinks to easily access resources from Discord such as profile pictures."
14 | - name: "og:description"
15 | property: "og:description"
16 | content: "Use Lanyard Quicklinks to easily access resources from Discord such as profile pictures."
17 | - name: "twitter:description"
18 | property: "twitter:description"
19 | content: "Use Lanyard Quicklinks to easily access resources from Discord such as profile pictures."
20 | ---
21 |
22 | # Quicklinks
23 |
24 | Lanyard quicklinks allow you to easily access resources from Discord, such as profile pictures.
25 |
26 | ### User Icons
27 |
28 | `https://api.lanyard.rest/.`
29 | Where `id` is the Discord user ID. `file_type` can be one of: `png`, `gif`, `webp`, `jpg`, or `jpeg`
30 |
--------------------------------------------------------------------------------
/src/content/api/self-hosting.md:
--------------------------------------------------------------------------------
1 | ---
2 | head:
3 | meta:
4 | - name: "og:title"
5 | property: "og:title"
6 | content: "Self-Hosting Lanyard"
7 | - name: "twitter:title"
8 | property: "twitter:title"
9 | content: "Self-Hosting Lanyard"
10 |
11 | - name: "description"
12 | property: "description"
13 | content: "Build Lanyard from source and self-host it using the Docker image."
14 | - name: "og:description"
15 | property: "og:description"
16 | content: "Build Lanyard from source and self-host it using the Docker image."
17 | - name: "twitter:description"
18 | property: "twitter:description"
19 | content: "Build Lanyard from source and self-host it using the Docker image."
20 | ---
21 |
22 | # Self-Hosting Lanyard
23 |
24 | Build the Docker image by cloning this repo and running:
25 |
26 | ```bash
27 | # The latest version is already on the docker hub, you can skip this step unless you would like to run a modified version.
28 | docker build -t phineas/lanyard:latest .
29 | ```
30 |
31 | If you don't already have a redis server you'll need to run one, here's the docker command to run one:
32 |
33 | ```bash
34 | docker run -d --name lanyard-redis -v docker_mount_location_on_host:/data redis
35 | ```
36 |
37 | And run Lanyard API server using:
38 |
39 | ```bash
40 | docker run --rm -it -p 4001:4001 -e REDIS_HOST=redis -e BOT_TOKEN= --link lanyard-redis:redis phineas/lanyard:latest
41 | ```
42 |
43 | You'll be able to access the API using **port 4001**.
44 |
45 | You also need to create a Discord bot and use its token above.
46 |
47 | Create a bot here: [https://discord.com/developers/applications](https://discord.com/developers/applications)
48 |
49 | **Make sure you enable** these settings in your bot settings:
50 |
51 | - Privileged Gateway Intents > **PRESENCE INTENT**
52 | - Privileged Gateway Intents > **SERVER MEMBERS INTENT**
53 |
54 | If you'd like to run Lanyard with `docker-compose`, here's an example:
55 |
56 | ```yaml
57 | version: "3.8"
58 |
59 | services:
60 | redis:
61 | image: redis
62 | restart: always
63 | container_name: lanyard_redis
64 | lanyard:
65 | image: phineas/lanyard:latest
66 | restart: always
67 | container_name: lanyard
68 | depends_on:
69 | - redis
70 | ports:
71 | - 4001:4001
72 | environment:
73 | BOT_TOKEN:
74 | REDIS_HOST: redis
75 | ```
76 |
77 | Note, that you're **hosting a http server, not https**. You'll need to use a **reverse proxy** such as [traefik](https://traefik.io/traefik/) if you want to secure your API endpoint.
78 |
--------------------------------------------------------------------------------
/src/content/api/working-with-websockets.md:
--------------------------------------------------------------------------------
1 | ---
2 | head:
3 | meta:
4 | - name: "og:title"
5 | property: "og:title"
6 | content: "Working with WebSockets"
7 | - name: "twitter:title"
8 | property: "twitter:title"
9 | content: "Working with WebSockets"
10 |
11 | - name: "description"
12 | property: "description"
13 | content: "Use Lanyard with WebSockets to achieve real-time presence updates."
14 | - name: "og:description"
15 | property: "og:description"
16 | content: "Use Lanyard with WebSockets to achieve real-time presence updates."
17 | - name: "twitter:description"
18 | property: "twitter:description"
19 | content: "Use Lanyard with WebSockets to achieve real-time presence updates."
20 | ---
21 |
22 | # Working with WebSockets
23 |
24 | The WebSocket server acts like a "real-time update data" server, each time a presence update is triggered, you'll receive the new data from the WS server. The Lanyard 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. [You can read more about WebSockets for web here](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket).
25 |
26 | 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.
27 |
28 | You should send `Opcode 2: Initialize` immediately after receiving Opcode 1.
29 |
30 | Example of `Opcode 2: Initialize`:
31 |
32 | ```js
33 | {
34 | op: 2,
35 | d: {
36 | // subscribe_to_ids should be an array of user IDs you want to subscribe to presences from
37 | // if Lanyard doesn't monitor an ID specified, it won't be included in INIT_STATE
38 | subscribe_to_ids: ["162969778699501569"]
39 | }
40 | }
41 | ```
42 |
43 | #### Subscribing to multiple user presences
44 |
45 | 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.
46 |
47 | #### Subscribing to a single user presence
48 |
49 | 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.
50 |
51 | #### Subscribing to every user presence
52 |
53 | 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.
54 |
55 | 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).
56 |
57 | ### List of Opcodes
58 |
59 | ::ListOpcodes
60 | ::
61 |
62 | ### Events
63 |
64 | Events are received on `Opcode 0: Event` - the event type will be part of the root message object under the `t` key.
65 |
66 | #### Example Event Message Objects
67 |
68 | `INIT_STATE`
69 |
70 | ```js
71 | {
72 | op: 0,
73 | seq: 1,
74 | t: "INIT_STATE",
75 | d: {
76 | "162969778699501569": {
77 | // Full Lanyard presence (see API docs above for example)
78 | }
79 | }
80 | }
81 | ```
82 |
83 | `PRESENCE_UPDATE`
84 |
85 | ```js
86 | {
87 | op: 0,
88 | seq: 2,
89 | t: "PRESENCE_UPDATE",
90 | d: {
91 | // Full Lanyard presence and an extra "user_id" field
92 | }
93 | }
94 | ```
95 |
96 | ### Error Codes
97 |
98 | 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.
99 |
100 | #### Types of Errors
101 |
102 | ::error-types
103 | ::
104 |
--------------------------------------------------------------------------------
/src/data/communityProjects.ts:
--------------------------------------------------------------------------------
1 | /*
2 | I will keep this file in case Lanyard updates readme and my script
3 | fails to parse it, I will revert back to this then.
4 | */
5 |
6 | interface CommunityProject {
7 | name: string;
8 | description: string;
9 | href?: string;
10 | owner?: string;
11 | }
12 |
13 | export const communityProjects: CommunityProject[] = [
14 | // add your project here
15 | {
16 | name: "cnrad/lanyard-profile-readme",
17 | description:
18 | "Utilize Lanyard to display your Discord Presence in your GitHub Profile",
19 | href: "https://github.com/cnrad/lanyard-profile-readme",
20 | },
21 | {
22 | name: "eggsy/vue-lanyard",
23 | description:
24 | "Lanyard API plugin for Vue which supports REST and WebSocket methods.",
25 | href: "https://github.com/eggsy/vue-lanyard",
26 | },
27 | {
28 | name: "barbarbar338/react-use-lanyard",
29 | description: "React hook for Lanyard - supports REST & WebSocket",
30 | href: "https://github.com/barbarbar338/react-use-lanyard",
31 | },
32 | {
33 | name: "alii/use-lanyard",
34 | description: "Another React hook for Lanyard that uses SWR",
35 | href: "https://github.com/alii/use-lanyard",
36 | },
37 | {
38 | name: "eggsy/lanyard-visualizer",
39 | description: "Beautifully display your Discord presence on a website",
40 | href: "https://lanyard-visualizer.netlify.app",
41 | },
42 | {
43 | name: "5elenay/hawser",
44 | description:
45 | "Lanyard API wrapper for python. Supports both REST and WebSocket.",
46 | href: "https://github.com/5elenay/hawser",
47 | },
48 | {
49 | name: "xaronnn/js-lanyard",
50 | description: "Use Lanyard in your Web App.",
51 | href: "https://github.com/xaronnn/js-lanyard/",
52 | },
53 | {
54 | name: "barbarbar338/go-lanyard",
55 | description: "Lanyard API wrapper for GoLang - supports REST & WebSocket",
56 | href: "https://github.com/barbarbar338/go-lanyard",
57 | },
58 | {
59 | name: "LeonardSSH/use-lanyard",
60 | description:
61 | "Lanyard with Composition API for Vue. Supports REST and WebSocket methods",
62 | href: "https://github.com/LeonardSSH/use-lanyard",
63 | },
64 | {
65 | name: "punctuations/use-listen-along",
66 | description:
67 | "Mock the discord 'Listen Along' feature within a react hook powered by the Lanyard API.",
68 | href: "https://github.com/punctuations/use-listen-along",
69 | },
70 | {
71 | name: "CesiumLabs/lanyard-graphql",
72 | description: "A GraphQL port of the Lanyard API.",
73 | href: "CesiumLabs/lanyard-graphql",
74 | },
75 | {
76 | name: "iGalaxyYT/svelte-lanyard",
77 | description: "A Lanyard API wrapper for Svelte. Supports REST & WebSocket.",
78 | href: "https://github.com/iGalaxyYT/svelte-lanyard",
79 | },
80 | {
81 | name: "xHyroM/denyard",
82 | description: "Lanyard API wrapper for Deno - Supports REST & WebSocket.",
83 | href: "https://github.com/xHyroM/denyard",
84 | },
85 | {
86 | name: "pxseu/lanyard-ui",
87 | description: "Lanyard visualizer focused on the KV aspect",
88 | href: "https://lanyard.sakurajima.cloud",
89 | },
90 | {
91 | name: "CompeyDev/discord-status-action",
92 | description:
93 | "Updates a file to include your discord status using the Lanyard API.",
94 | href: "https://github.com/CompeyDev/discord-status-action",
95 | },
96 | ];
97 |
--------------------------------------------------------------------------------
/src/data/usedBy.ts:
--------------------------------------------------------------------------------
1 | /*
2 | I will keep this file in case Lanyard updates readme and my script
3 | fails to parse it, I will revert back to this then.
4 | */
5 |
6 | export const usedBy = [
7 | // add your website to the bottom of the list
8 | "alistair.cloud",
9 | "timcole.me",
10 | "dstn.to",
11 | "phineas.io",
12 | "slayter.dev",
13 | "cnrad.dev",
14 | "dont-ping.me",
15 | "eggsy.xyz",
16 | "crugg.de",
17 | "igalaxy.dev",
18 | "itspolar.dev",
19 | "vasc.dev",
20 | "eri.gg",
21 | "voided.dev",
22 | "thicc-thighs.de",
23 | "chezzer.dev",
24 | "looskie.com",
25 | "barbarbar338.fly.dev",
26 | "5elenay.github.io",
27 | "notnick.io",
28 | "kevinthomas.codes",
29 | "loom4k.me",
30 | "presence.im",
31 | "jackbailey.dev",
32 | "345dev.me",
33 | "d3r1n.com",
34 | "vops.cc",
35 | "emirkabal.com",
36 | "wosleyv.dev",
37 | "aidan.pw",
38 | "anaxes.codes",
39 | "avyanshralph.xyz",
40 | "maki.cafe",
41 | "cenap.js.org",
42 | "rexulec.com",
43 | "isaackogan.com",
44 | "krypton.ninja",
45 | "voltages.me",
46 | "tysm.dev",
47 | "ggorg.tk",
48 | "hexiaq.cf",
49 | "darkshiny.me",
50 | "noirs.me",
51 | "2m4u.netlify.app",
52 | "eleven.js.org",
53 | "roxza.me",
54 | "keaton.codes",
55 | "itsmebravo.dev",
56 | "cimok.co.uk",
57 | "winnerose.live",
58 | "alysum.vercel.app",
59 | "rovi.me",
60 | "snazzah.com",
61 | "itsnp.cf",
62 | "sayanzyx.netlify.app",
63 | "lanyard-card-example.netlify.app",
64 | "niskii.denkylabs.com",
65 | "falsis.ga",
66 | "sundei.de",
67 | "sanct.me",
68 | "leonard.sh",
69 | "ithundxr.dev",
70 | "callumdev.xyz",
71 | "jvsh.me",
72 | ];
73 |
--------------------------------------------------------------------------------
/src/pages/api/[...slug].vue:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
30 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
63 |
64 |
65 |
66 |
67 |
101 |
--------------------------------------------------------------------------------
/src/pages/index.vue:
--------------------------------------------------------------------------------
1 |
44 |
45 |
46 |
47 |
48 |
53 | Expose your Discord activities to a RESTful API and WebSocket
54 |
55 |
56 |
75 |
76 |
81 |
87 |
88 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
How?
102 |
103 |
104 | Lanyard is a service that makes it super easy to export your live
105 | Discord presence to an API endpoint
106 | (api.lanyard.rest/v1/users/:your_id)
and to a WebSocket
107 | for you to use wherever you want. It is fully open-source and
108 | powerful. You can use the API without deploying anything yourself -
109 | but if you want to self host it, you have the option to, though it'll
110 | require a tiny bit of configuration.
111 |
112 |
113 |
114 |
115 |
How Does Monitoring Work?
116 |
117 |
118 | Lanyard uses a basic Discord Bot (which is open source as well) and
119 | monitors every user in
120 | its Discord server . On
121 | each presence change, Lanyard sends a WS signal to update the API
122 | response.
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | Try It Yourself
131 |
132 |
133 |
134 |
141 |
142 |
143 |
144 |
145 | User
146 |
147 | {{ result.lanyard.data?.discord_user?.username || "Unknown" }}
148 |
149 |
150 |
151 |
152 |
153 |
User is
154 |
158 |
{{ getStatus.name }}
159 |
160 |
161 |
162 |
163 | Listening to Spotify
164 |
165 | {{ result.lanyard.data?.listening_to_spotify ? "Yes" : "No" }}
166 |
167 |
168 |
169 |
170 |
175 |
181 |
182 |
183 | Did you join the Discord server?
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
200 |
201 |
The magic
202 |
203 |
204 | Lanyard API is meant to create whatever you want using the data it
205 | provides. People have already started creating amazing projects. Let's
206 | preview one of them,
207 | lanyard-profile-readme . You can embed the result in your website or GitHub-like readme.
213 |
214 |
215 |
216 |
221 |
222 |
223 | {{
224 | playgroundInput && magicPreviewError === false
225 | ? "🤯 Now, isn't that cool?"
226 | : "✨ Enter user ID to see the magic"
227 | }}
228 |
229 |
230 |
231 |
232 |
233 |
240 |
241 |
249 |
250 |
255 | Make sure you put the right ID and you joined Lanyard's Discord
256 | server.
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
267 |
Community Projects
268 |
269 |
270 |
271 | {{ `${pageData.projects.length} in total` }}
272 |
273 |
274 |
275 |
280 |
281 |
282 |
283 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
311 |
312 |
313 |
314 |
315 |
316 | Used By
317 |
318 |
319 |
320 |
321 |
322 | An error occured.
323 |
324 |
325 |
333 | {{ website }}
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
--------------------------------------------------------------------------------
/src/public/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eggsy/lanyard-web/285050628a36b52c1eb8f9f3b6192e102bce001b/src/public/icon.png
--------------------------------------------------------------------------------
/src/public/social-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eggsy/lanyard-web/285050628a36b52c1eb8f9f3b6192e102bce001b/src/public/social-image.png
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | theme: {
3 | extend: {
4 | colors: {
5 | brand: "#313336",
6 | },
7 | },
8 | },
9 | plugins: [require("@tailwindcss/typography")],
10 | };
11 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // https://v3.nuxtjs.org/concepts/typescript
3 | "extends": "./.nuxt/tsconfig.json"
4 | }
5 |
--------------------------------------------------------------------------------