Skip to content

Commit

Permalink
erm hehe
Browse files Browse the repository at this point in the history
  • Loading branch information
yofukashino committed Mar 20, 2024
1 parent a6327ed commit f8da399
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 82 deletions.
54 changes: 50 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,62 @@ Make your experience better with spotify links.

Like Playing directly or adding in queue. (Also opening directly in app)

Direct Download Link: [dev.tharki.Distify.asar](https://github.com/YofukashiNo/Distify/releases/latest/download/dev.tharki.Distify.asar)
Direct Download Link:
[![dev.yofukashino.Distify.asar](https://img.shields.io/github/downloads/YofukashiNo/MessageLinkEmbeds/total.svg?style=social&label=Direct%20Download)](https://github.com/YofukashiNo/Distify/releases/latest/download/dev.yofukashino.Distify.asar)

Install Link:
[![Safe](https://img.shields.io/github/downloads/YofukashiNo/MessageLinkEmbeds/total.svg?style=social&label=Install%20in%20Replugged&logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMjQ1NzkgMjQ1NzkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnNYbGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sU3BhY2U9InByZXNlcnZlIiB4bWxuczpzZXJpZj0iaHR0cDovL3d3dy5zZXJpZi5jb20vIiBjbGFzcz0iX3BsdWdfM2J3NmNfMjIiIHN0eWxlPSJmaWxsLXJ1bGU6IGV2ZW5vZGQ7IGNsaXAtcnVsZTogZXZlbm9kZDsgc3Ryb2tlLWxpbmVqb2luOiByb3VuZDsiPjxnPjxjbGlwUGF0aCBpZD0iX2NsaXAxIj48cGF0aCBkPSJNMjIyMjAuMywyMjQ3NC44YzM5LjI1LDQ0LjU3MSA3MS40NjcsOTQuODcxIDk1LjU0MiwxNDkuMTYzYzE2NC4wOTYsMzY4LjQyNSAxNjIuNDI5LDc5Ni42MDggLTE3Ljk0MiwxMTcwLjFjLTQzLjE0MSw4OS4zMzMgLTk1LjA4NywxNzIuNiAtMTU0LjUwOCwyNDguOTcxYy0yODEuNzMzLDM2My41NjcgLTc2OS43NjcsNDk3LjI5NiAtMTE5Ny40OCwzMjguMTI5Yy0xNzc3LjgyLC02NzguMzc1IC00MTIxLjMyLC0xMjgyLjAzIC01NjcwLjA0LC0yMTQ1Ljg1Yy0zMDExLjE4LC0xNjc5LjU0IC01MDg0LjY3LC0zMjgzLjI4IC0zNjQ2LjE3LC03NzMxLjI5YzI2LjEzNywtODAuODgzIDk4LjgxNiwtMTM3Ljc1NCAxODMuNjA4LC0xNDMuNjcxYzE4MDUuNzcsLTEzNy4xMDggMzQxMC40LC0xMzkyLjE5IDM5MDUuNzIsLTMyNDAuNzVjMTYwLjg1LC02MDAuMzEyIDMxMi4yMjksLTExNjUuMjYgNDMyLjc3NSwtMTYxNS4xNWM3MC44NTgsLTI2NC40NDEgMzMuNzYyLC01NDYuMiAtMTAzLjEyMSwtNzgzLjI5MWMtMTM2Ljg4NywtMjM3LjA5MiAtMzYyLjM1LC00MTAuMDk2IC02MjYuNzkyLC00ODAuOTVsLTQyMi42NzksLTExMy4yNTlsODc4LjQ5MiwtMzI3OC41OGM1MC40NSwtMTg4LjI3MSAyNC4wMzcsLTM4OC44NzUgLTczLjQxNywtNTU3LjY3NWMtOTcuNDU4LC0xNjguOCAtMjU3Ljk3OSwtMjkxLjk3MSAtNDQ2LjI1LC0zNDIuNDE3Yy0xODguMjcxLC01MC40NSAtMzg4Ljg3NSwtMjQuMDM3IC01NTcuNjc1LDczLjQxN2MtMTY4LjgsOTcuNDU4IC0yOTEuOTcxLDI1Ny45NzkgLTM0Mi40MTcsNDQ2LjI1bC04NzguNDkxLDMyNzguNThsLTI3OTguNTUsLTc0OS44NjZsODc4LjQ5NiwtMzI3OC41OGM1MC40NDYsLTE4OC4yNyAyNC4wMzcsLTM4OC44NyAtNzMuNDIxLC01NTcuNjdjLTk3LjQ1NCwtMTY4LjggLTI1Ny45NzUsLTI5MS45NzUgLTQ0Ni4yNSwtMzQyLjQyMWMtMC4xMzMsLTAuMDM4IC0wLjI2NywtMC4wNzEgLTAuNDA0LC0wLjEwOWMtMTg4LjE2MywtNTAuNDIgLTM4OC42NSwtMjQuMDI1IC01NTcuMzU0LDczLjM4Yy0xNjguNzA1LDk3LjQgLTI5MS44MDUsMjU3LjgyOSAtMzQyLjIyNSw0NDUuOTkxbC04NzguNiwzMjc4Ljk5bC00MjIuNjgsLTExMy4yNTljLTI2NC40NDEsLTcwLjg1OCAtNTQ2LjIsLTMzLjc2MiAtNzgzLjI5MSwxMDMuMTIxYy0yMzcuMDkyLDEzNi44ODQgLTQxMC4wOTYsMzYyLjM0NiAtNDgwLjk1NCw2MjYuNzg4Yy0xMjAuNTUsNDQ5Ljg5NiAtMjcxLjkyNSwxMDE0Ljg0IC00MzIuNzgsMTYxNS4xNWMtNDc4LjM3NSwxNzg1LjMzIDIxNi4xMjUsMzYwOC42IDE2MTEuMTUsNDY1MS43MWM3Mi4zODgsNTMuMzg4IDEwMi4yNSwxNDcuMjU4IDc0LjAxNywyMzIuNjU4Yy0xNzAzLjcsNTE1OC41IDM5MC43NzEsNzY5NS42MiAyMzc2LjIsOTI4Mi4zM2M0MTMuODA4LDMzMC43MDQgODY2LjUzOCw2NDIuNDIxIDEzNDAuNjQsOTMxLjYwNGMxMzIuMjQyLDgxLjA2NyAxOTQuNDgzLDI0MC4xNSAxNTIuMzY3LDM4OS40MzNjLTQyLjExNywxNDkuMjg0IC0xNzguMzI2LDI1Mi4zODQgLTMzMy40MzQsMjUyLjM4NGMtMjgzNy4yOCwwLjc3MSAtOTE5OC41NCwwLjc3MSAtOTE5OC41NCwwLjc3MWMtNzY3LjA2MiwtMCAtMTM4OC44OSwtNjIxLjgyNSAtMTM4OC44OSwtMTM4OC44OWwtMCwtMjE4MDAuMmMtMCwtMzY4LjUzMyAxNDYuNDcxLC03MjEuOTYyIDQwNy4xNjIsLTk4Mi40NThjMjYwLjY5MiwtMjYwLjQ5NiA2MTQuMjMsLTQwNi43MDQgOTgyLjc2MywtNDA2LjQyOWMzNjA5LjE3LDIuNyAxMzAwMCw5LjcyMSAxMzAwMCw5LjcyMWMxNjM2LjAzLC0wIDMyMDUuMDYsNjQ5LjkxMiA0MzYxLjkyLDE4MDYuNzZjMTE1Ni44NSwxMTU2Ljg1IDE4MDYuNzYsMjcyNS44OCAxODA2Ljc2LDQzNjEuOTJsMCw0NDUwLjc1YzAsMTYzNi4wMyAtNjQ5LjkxMiwzMjA1LjA2IC0xODA2Ljc2LDQzNjEuOTJjLTE0OTMuNDYsMTQ5My40NSAtMTU2OS41NSwzODkwLjMgLTE3My44MjEsNTQ3NS40NmM4NzguMyw5OTcuNTE3IDE1NzkuNjUsMTc5NC4wNSAxNzY3LjM2LDIwMDcuMjVsLTAuMDA0LDAuMDQxWiI+PC9wYXRoPjwvY2xpcFBhdGg+PGcgY2xpcC1wYXRoPSJ1cmwoI19jbGlwMSkiPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIyNDU3OSIgaGVpZ2h0PSIyNDU3OSIgc3R5bGU9ImZpbGw6IHVybCgmcXVvdDsjX0xpbmVhcjImcXVvdDspOyI+PC9yZWN0PjwvZz48L2c+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJfTGluZWFyMiIgeDE9IjAiIHkxPSIwIiB4Mj0iMSIgeTI9IjAiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDI0NTc5LC0yNDU3OSwyNDU3OSwyNDU3OSwwLDI0NTc5KSI+PHN0b3Agb2Zmc2V0PSIwIiBzdHlsZT0ic3RvcC1jb2xvcjogcmdiKDI1NSwgMzIsIDYyKTsgc3RvcC1vcGFjaXR5OiAxOyI+PC9zdG9wPjxzdG9wIG9mZnNldD0iMSIgc3R5bGU9InN0b3AtY29sb3I6IHJnYig4MCwgNiwgMjU1KTsgc3RvcC1vcGFjaXR5OiAxOyI+PC9zdG9wPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjwvc3ZnPg==)](https://replugged.dev/install?identifier=YofukashiNo/Distify&source=github)

![distify](https://i.imgur.com/i7r0j9L.png)

[![Install in Replugged](https://img.shields.io/badge/-Install%20in%20Replugged-blue?style=for-the-badge&logo=none)](https://replugged.dev/install?identifier=YofukashiNo/Distify&source=github)
---

![image](https://i.imgur.com/i7r0j9L.png)
# FAQ

### How to install a plugin?
<details open>
<summary>Automatic</summary>

- Simply click on install link and thats all <3
</details>
<details>
<summary>Manual</summary>

> For Contributing: [Make a pr thats all.]
- Click on Direct Download Link and save the file
- Open Replugged Plugin Settings
- Click on "Open Plugins Folder" button
- Paste downloaded file in folder that opened
</details>

### How Do I contribute?
- Just make a pull request

### How Do I support without pull request?
- You Can Donate on my [ko-fi](https://ko-fi.com/yofukashino) or UPI at `yofukashi.no.singh@fam`

[![Buy Me a Coffee at ko-fi.com](https://storage.ko-fi.com/cdn/kofi3.png?v=3)](https://ko-fi.com/yofukashino)

### Where can I find other plugins by you?

You can find them [here](https://github.com/YofukashiNo/RepluggedPlugins)

### This plugin isn't listed in the all plugin list?

PRs are appreciated or just make an issue on the [repo](https://github.com/YofukashiNo/RepluggedPlugins)


### Where can I find the support?

~~You can make post in support channel of replugged server and ping me.~~

OR

There is support server for all the plugins. You can join it here:

[![Support Server](https://discordapp.com/api/guilds/919649417005506600/widget.png?style=banner3)](https://discord.gg/SgKSKyh9gY)



# Who is the author of these plugins?

[![Discord Presence](https://lanyard.cnrad.dev/api/1121961711080050780?hideDiscrim=true&idleMessage=Leave%20the%20kid%20alone...)](https://discordapp.com/users/1121961711080050780)
6 changes: 3 additions & 3 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"id": "dev.tharki.Distify",
"id": "dev.yofukashino.Distify",
"name": "Distify",
"description": "Make your experience better with spotify links.",
"author": {
"name": "Ahlawat",
"name": "Nanakusa",
"discordID": "1121961711080050780",
"github": "YofukashiNo"
},
"version": "1.0.3",
"updater": {
"type": "store",
"id": "dev.tharki.Distify"
"id": "dev.yofukashino.Distify"
},
"license": "MIT",
"type": "replugged-plugin",
Expand Down
25 changes: 8 additions & 17 deletions src/Components/MenuItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ContextMenu } from "replugged/components";
import { PluginLogger } from "../index";
import Utils from "../lib/utils";
import Icons from "./Icons";
import Types from "../types";

export const noAccounts = (): React.ReactElement => {
return (
Expand All @@ -17,10 +16,7 @@ export const noAccounts = (): React.ReactElement => {
);
};

export const addToQueue = (
SpotifyLinks: string[][],
SpotifyAccount: Types.SpotifyAccounts,
): React.ReactElement => {
export const addToQueue = (SpotifyLinks: string[][]): React.ReactElement => {
if (SpotifyLinks.length === 1) {
const [, type, id, name] = SpotifyLinks[0];
return (
Expand All @@ -32,7 +28,7 @@ export const addToQueue = (
icon={() => <Icons.queue width="16" height="16" />}
action={async () => {
try {
await Utils.queue(type, id, SpotifyAccount.accessToken);
await Utils.queue(type, id);
ToastUtils.toast("Successfully Queued on Spotify", ToastUtils.Kind.SUCCESS, {
duration: 5000,
});
Expand All @@ -54,8 +50,7 @@ export const addToQueue = (
icon={() => <Icons.queue width="16" height="16" />}
action={async () => {
try {
for (const [, type, id] of SpotifyLinks)
await Utils.queue(type, id, SpotifyAccount.accessToken);
for (const [, type, id] of SpotifyLinks) await Utils.queue(type, id);
ToastUtils.toast("Successfully Queued on Spotify", ToastUtils.Kind.SUCCESS, {
duration: 5000,
});
Expand All @@ -75,7 +70,7 @@ export const addToQueue = (
icon={() => <Icons.queue width="16" height="16" />}
action={async () => {
try {
await Utils.queue(type, id, SpotifyAccount.accessToken);
await Utils.queue(type, id);
ToastUtils.toast("Successfully Queued on Spotify", ToastUtils.Kind.SUCCESS, {
duration: 5000,
});
Expand All @@ -93,10 +88,7 @@ export const addToQueue = (
);
};

export const play = (
SpotifyLinks: string[][],
SpotifyAccount: Types.SpotifyAccounts,
): React.ReactElement => {
export const play = (SpotifyLinks: string[][]): React.ReactElement => {
if (SpotifyLinks.length === 1) {
const [, type, id, name] = SpotifyLinks[0];
return (
Expand All @@ -108,7 +100,7 @@ export const play = (
icon={() => <Icons.play width="16" height="16" />}
action={async () => {
try {
await Utils.play(type, id, SpotifyAccount.accessToken);
await Utils.play(type, id);
ToastUtils.toast("Successfully Played on Spotify", ToastUtils.Kind.SUCCESS, {
duration: 5000,
});
Expand All @@ -130,8 +122,7 @@ export const play = (
icon={() => <Icons.play width="16" height="16" />}
action={async () => {
try {
for (const [, type, id] of SpotifyLinks)
await Utils.play(type, id, SpotifyAccount.accessToken);
for (const [, type, id] of SpotifyLinks) await Utils.play(type, id);
ToastUtils.toast("Successfully Played on Spotify", ToastUtils.Kind.SUCCESS, {
duration: 5000,
});
Expand All @@ -151,7 +142,7 @@ export const play = (
icon={() => <Icons.play width="16" height="16" />}
action={async () => {
try {
await Utils.play(type, id, SpotifyAccount.accessToken);
await Utils.play(type, id);
ToastUtils.toast("Successfully Played on Spotify", ToastUtils.Kind.SUCCESS, {
duration: 5000,
});
Expand Down
2 changes: 2 additions & 0 deletions src/lib/requiredModules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export const ConnectedAccountsStore =
webpack.getByStoreName<Types.ConnectedAccountsStore>("ConnectedAccountsStore");

export const ElementParser = webpack.getByProps<Types.ElementParser>("sanitizeUrl", "sanitizeText");

export const SpotifyStore = webpack.getByStoreName<Types.SpotifyStore>("SpotifyStore");
101 changes: 54 additions & 47 deletions src/lib/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,44 @@ import { contextMenu as ContextMenuUtils, React } from "replugged/common";
import { ContextMenu } from "replugged/components";
import { PluginLogger } from "../index";
import { BASE_URL, BASE_URL_PLAYER } from "./consts";
import { ConnectedAccountsStore } from "./requiredModules";
import { ConnectedAccountsStore, SpotifyStore } from "./requiredModules";
import MenuItems from "../Components/MenuItems";
import Types from "../types";
export const customCacheSpotifyMeta = new Map<string, string[]>();
export const ensureSpotifyPlayer = (): Promise<{
socket?: Types.SpotifySocket;
device?: Types.SpotifyDevice;
}> => {
const activePlayer = SpotifyStore.getActiveSocketAndDevice();
if (activePlayer) return Promise.resolve(activePlayer);
const playableDevices = SpotifyStore.getPlayableComputerDevices();
if (playableDevices.length > 0) {
const [{ socket, device }] = playableDevices;
return Promise.resolve({
socket,
device,
});
}
return new Promise((res) => {
const timer = { timeout: null };
const changeListerner = () => {
const playableDevices = SpotifyStore.getPlayableComputerDevices();
const [{ socket, device }] = playableDevices;
clearTimeout(timer?.timeout);
SpotifyStore.removeChangeListener(changeListerner);
res({
socket,
device,
});
};
SpotifyStore.addChangeListener(changeListerner);
timer.timeout = setTimeout(() => {
SpotifyStore.removeChangeListener(changeListerner);
res({});
}, 2500);
open("spotify:");
});
};
export const error = async (res): Promise<Error> => {
switch (res.status) {
case 401:
Expand All @@ -21,13 +55,14 @@ export const error = async (res): Promise<Error> => {
return new Error("Unknown Error, Check the console and report the dev");
}
};
export const play = async (type: string, id: string, accessToken: string): Promise<void> => {
if (!accessToken) {
export const play = async (type: string, id: string): Promise<void> => {
const { socket, device } = await ensureSpotifyPlayer();
if (!socket?.accessToken) {
PluginLogger.error("Please link your Spotify to Discord in Settings > Connections");
return;
}

const SpotifyResponse = await fetch(`${BASE_URL_PLAYER}/play`, {
const SpotifyResponse = await fetch(`${BASE_URL_PLAYER}/play?device_id=${device.id}`, {
method: "PUT",
body: JSON.stringify(
type === "track"
Expand All @@ -36,7 +71,7 @@ export const play = async (type: string, id: string, accessToken: string): Promi
),
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
Authorization: `Bearer ${socket?.accessToken}`,
},
});
if (SpotifyResponse.ok) {
Expand All @@ -45,19 +80,21 @@ export const play = async (type: string, id: string, accessToken: string): Promi
throw await error(SpotifyResponse);
};

export const queue = async (type: string, id: string, accessToken: string): Promise<void> => {
if (!accessToken) {
export const queue = async (type: string, id: string): Promise<void> => {
const { socket, device } = await ensureSpotifyPlayer();
if (!socket?.accessToken) {
PluginLogger.error("Please link your Spotify to Discord in Settings > Connections");
return;
}

const SpotifyResponse = await fetch(
`${BASE_URL_PLAYER}/queue?uri=${encodeURIComponent(`spotify:${type}:${id}`)}`,
`${BASE_URL_PLAYER}/queue?uri=${encodeURIComponent(`spotify:${type}:${id}`)}&device_id=${
device.id
}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
Authorization: `Bearer ${socket?.accessToken}`,
},
},
);
Expand Down Expand Up @@ -104,7 +141,6 @@ export const mapMenuItems = (
})
.then((res) => res.json())
.catch(() => ({ name: "Error Fetching Name" }));
console.log(SpotifyResponse);
if (SpotifyResponse?.name)
customCacheSpotifyMeta.set(id, [_, type, id, SpotifyResponse?.name]);
return [_, type, id, SpotifyResponse?.name ?? "Error Fetching Name"];
Expand All @@ -131,24 +167,10 @@ export const mapMenuItems = (
if ((type as { data: boolean }).data) {
return SpotifyMeta;
}
if (SpotifyAccounts.length === 1) {
return [
type.play && MenuItems.play(SpotifyMeta, SpotifyAccounts[0]),
type.queue && MenuItems.addToQueue(SpotifyMeta, SpotifyAccounts[0]),
];
}
return SpotifyAccounts.map((SpotifyAccount) => {
return (
<ContextMenu.MenuItem
label={SpotifyAccount.name}
id={`spotify-account-${SpotifyAccount.name}`}>
{...[
type.play && MenuItems.play(SpotifyMeta, SpotifyAccount),
type.queue && MenuItems.addToQueue(SpotifyMeta, SpotifyAccount),
]}
</ContextMenu.MenuItem>
);
});
return [
type.play && MenuItems.play(SpotifyMeta),
type.queue && MenuItems.addToQueue(SpotifyMeta),
];
} catch {
return [];
}
Expand Down Expand Up @@ -179,13 +201,12 @@ export const manipulateMenu = (
message: Types.Message,
menu: { children: React.ReactElement[] },
): React.ReactElement | void => {
console.log(menu);
const MenuGroup = menu?.children?.find?.((c) => c?.props?.id === "distify") ?? (
<ContextMenu.MenuGroup />
);
MenuGroup.props.id = "distify";
if (!menu?.children?.some?.((c) => c?.props?.id === "distify"))
menu?.children.splice(1, 0, MenuGroup);
menu?.children.splice(-1, 0, MenuGroup);
const SpotifyLinks = Array.from(
message.content.matchAll(/open.spotify.com\/(album|track|playlist)\/([^?]+)/g) as string[][] &
IterableIterator<RegExpMatchArray>,
Expand All @@ -198,22 +219,8 @@ export const manipulateMenu = (
data: true,
}) as string[][];
if (SpotifyLinks.length <= 0) return;
if (SpotifyMeta && SpotifyAccounts.length === 1) {
MenuGroup.props.children = [
MenuItems.play(SpotifyMeta, SpotifyAccounts[0]),
MenuItems.addToQueue(SpotifyMeta, SpotifyAccounts[0]),
];
} else if (SpotifyMeta) {
MenuGroup.props.children = SpotifyAccounts.map((SpotifyAccount) => (
<ContextMenu.MenuItem
label={SpotifyAccount.name}
id={`spotify-account-${SpotifyAccount.name}`}>
{...[
MenuItems.play(SpotifyMeta, SpotifyAccount),
MenuItems.addToQueue(SpotifyMeta, SpotifyAccount),
]}
</ContextMenu.MenuItem>
));
if (SpotifyMeta) {
MenuGroup.props.children = [MenuItems.play(SpotifyMeta), MenuItems.addToQueue(SpotifyMeta)];
}
};

Expand Down
Loading

0 comments on commit f8da399

Please sign in to comment.