Skip to content

Commit

Permalink
Migration (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
AnonymousX86 authored May 17, 2023
2 parents ecbdf58 + 9a5f35f commit ac9a5ed
Show file tree
Hide file tree
Showing 20 changed files with 433 additions and 121 deletions.
22 changes: 18 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
# Spoyt

Spotify to YouTube Discord link converter.
Spotify to YouTube; Discord and Guilded link converter.

## Usage

Just send a message with share link from Spotify. Bot will automatically find
the track in Spotify database, and search its name and artists in YouTube.
If possible, it will try to delete your message, but you can disable it
by permitting it by permissions.
by permitting permissions.

## Guilded
Invite the bot by one of following links:
- Discord: https://discord.com/api/oauth2/authorize?client_id=948274806325903410&permissions=3072&scope=bot
- Guilded: https://www.guilded.gg/b/93177486-3a1d-4464-a202-1ddd6354844b

Guilded version: [AnonymousX86/spoyt-guilded](https://github.com/AnonymousX86/spoyt-guilded)
## Support

You can join one of my servers (or both):

- Discord: [discord.gg/SRdmrPpf2z](https://discord.gg/SRdmrPpf2z)
- Guilded: [guilded.gg/Anonymous-Canteen](https://guilded.gg/Anonymous-Canteen)

## How to run

Make sure you have Python `>=3.8` installed.
```
[py|python|python3] -(O|OO)m Spoyt.[Discord|Guilded]
```

Empty file added Spoyt/Discord/__init__.py
Empty file.
28 changes: 28 additions & 0 deletions Spoyt/Discord/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
from logging import INFO, basicConfig

from discord import Activity, ActivityType, Client, Intents
from rich.logging import RichHandler

from Spoyt.logging import log
from Spoyt.wrapper import main

if __name__ == '__main__':
basicConfig(
level=INFO,
format='%(message)s',
datefmt='[%x]',
handlers=[RichHandler(rich_tracebacks=True)]
)
log.info('Starting Discord bot')
intents = Intents.default()
intents.message_content = True
client = Client(
max_messages=None,
intents=intents,
activity=Activity(
name='Spotify & YouTube',
type=ActivityType.listening
)
)
main(client, __package__)
Empty file added Spoyt/Guilded/__init__.py
Empty file.
19 changes: 19 additions & 0 deletions Spoyt/Guilded/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from logging import INFO, basicConfig

from guilded import Client
from rich.logging import RichHandler

from Spoyt.logging import log
from Spoyt.wrapper import main

if __name__ == '__main__':
basicConfig(
level=INFO,
format='%(message)s',
datefmt='[%x]',
handlers=[RichHandler(rich_tracebacks=True)]
)
log.info('Starting Guilded bot')
client = Client()
main(client, __package__)
97 changes: 12 additions & 85 deletions Spoyt/__main__.py
Original file line number Diff line number Diff line change
@@ -1,90 +1,17 @@
# -*- coding: utf-8 -*-
from os import getenv
from logging import INFO, basicConfig

from discord import Client, Intents, Message, Embed, Color, \
ActivityType, Activity, NotFound, Forbidden

from Spoyt.spotify_api import search_spotify, model_track, TrackEmbed
from Spoyt.youtube_api import find_youtube_id


def main():
intents = Intents.default()
intents.message_content = True

client = Client(intents=intents)
client.youtube = None

@client.event
async def on_ready():
print(f'Logged in as {client.user}')
await client.change_presence(
activity=Activity(
name='Spotify & YouTube',
type=ActivityType.listening
)
)

@client.event
async def on_message(message: Message):
if not message.content.startswith('https://open.spotify.com/track/'):
return

msg = await message.channel.send(embed=Embed(
title=':hourglass_flowing_sand: Spotify link found!',
description='Connecting to super secret database...',
color=Color.green()
))

track_id = message.content.split('?')[0].split('&')[0].split('/')[-1]
spotify_query = search_spotify(track_id)

if not spotify_query:
await msg.edit(embed=Embed(
title='Oh no',
description='Spotify is out of service',
color=Color.red()
))
return

track = model_track(spotify_query)
track_embed = TrackEmbed(track)

try:
await message.delete()
except Forbidden or NotFound:
pass
else:
track_embed.add_author(message.author)

await msg.edit(embeds=[track_embed, Embed(
title=':hourglass_flowing_sand: Searching YouTube',
color=Color.blurple()
)])

video_id_found, result = find_youtube_id(
query='{} {}'.format(track.name, ' '.join(track.artists))
)

if not video_id_found:
await msg.edit(embeds=[track_embed, Embed(
title='Video not found',
description=result,
color=Color.dark_red()
)])
return

await msg.edit(embeds=[track_embed, Embed(
title='Best YouTube result',
color=Color.blurple()
)])

await message.channel.send(
content=f'https://www.youtube.com/watch?v={result}'
)

client.run(getenv('BOT_TOKEN'))
from rich.logging import RichHandler

from Spoyt.logging import log

if __name__ == '__main__':
main()
basicConfig(
level=INFO,
format='%(message)s',
datefmt='[%x]',
handlers=[RichHandler(rich_tracebacks=True)]
)
log.info('This is general Spoyt module.')
log.info('To run specific bot please run "Discord" or "Guilded" module.')
log.info('Remember to set "BOT_TOKEN" environment variables.')
Empty file added Spoyt/embeds/__init__.py
Empty file.
16 changes: 16 additions & 0 deletions Spoyt/embeds/color.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
from discord import Color as DiscordColor
from guilded import Color as GuildedColor

from Spoyt.env_check import is_discord, is_guilded

if is_discord():
DEFAULT = DiscordColor.blurple()
elif is_guilded():
DEFAULT = GuildedColor.gilded()
else:
DEFAULT = 0xCCCCCC

GREEN = 0x2ECC71
RED = 0xFF0000
DARK_RED = 0x992D22
25 changes: 25 additions & 0 deletions Spoyt/embeds/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
from Spoyt.embeds.definitions import BaseDiscordEmbed, BaseGuildedEmbed, EmbedDict
from Spoyt.env_check import current_platform, is_discord, is_guilded
from Spoyt.logging import log


def create_embed(data: EmbedDict) -> BaseDiscordEmbed or BaseGuildedEmbed:
embed = BaseDiscordEmbed if is_discord() else BaseGuildedEmbed if is_guilded else None
if type(embed) is None:
log.critical(f'Platform is "{current_platform()}" which is not good.')
return

embed = embed(
title=data.title,
description=data.description,
color=data.color
)
for field in data.fields:
embed.add_field(
name=field.name,
value=field.value,
inline=field.inline
)
if url := data.thumbnail_url:
embed.set_thumbnail(url=url)
119 changes: 119 additions & 0 deletions Spoyt/embeds/definitions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
from discord import Embed as DiscordEmbed, Color as DiscordColor
from guilded import Embed as GuiledEmbed, Color as GuildedColor

from Spoyt.embeds.color import DEFAULT, DARK_RED, GREEN, RED
from Spoyt.env_check import is_discord, is_guilded
from Spoyt.spotify_api import Track
from Spoyt.youtube_api import YouTubeResult


class BaseDiscordEmbed(DiscordEmbed):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
if 'color' not in kwargs.keys():
self.color = DiscordColor.blurple()


class BaseGuildedEmbed(GuiledEmbed):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
if 'color' not in kwargs.keys():
self.color = GuildedColor.gilded()


class EmbedField:
def __init__(
self,
name: str,
value: str,
inline: bool = True
) -> None:
self.name = name
self.value = value
self.inline = inline


class EmbedDict:
def __init__(
self,
title: str = None,
description: str = None,
color: int = DEFAULT,
fields: list[EmbedField] = [],
thumbnail_url: str = None
) -> None:
self.title = title
self.description = description
self.color = color
self.fields = fields
self.thumbnail_url = thumbnail_url


def markdown_url(url: str) -> str:
return (
'<{0}>' if is_discord() else
'[{0}]({0})' if is_guilded() else
'{0}'
).format(url)


def track_to_embed(track: Track) -> EmbedDict:
return EmbedDict(
title=track.name,
description=markdown_url(track.track_url),
color=GREEN,
fields=[
EmbedField(
name='Artist{}'.format('' if track.is_single_artist else 's'),
value=', '.join(track.artists),
inline=track.is_single_artist
),
EmbedField(
name='Released',
value=track.release_date
)
],
thumbnail_url=track.album_url
)


def video_to_embed(video: YouTubeResult) -> EmbedDict:
return EmbedDict(
title=video.title,
description=markdown_url(video.video_link),
fields=[
EmbedField(
name='Description',
value=video.description,
inline=False
),
EmbedField(
name='Published',
value=video.published_date
)
],
thumbnail_url=video.video_thumbnail
)


LINK_FOUND = EmbedDict(
title='\u23f3 Spotify link found!',
description='Connecting to super secret database\u2026',
color=GREEN
),

SPOTIFY_UNREACHABLE = EmbedDict(
title='Oh no',
description='Spotify is out of service',
color=RED
),

SEARCHING_YOUTUBE = EmbedDict(
title='\u23f3 Searching YouTube'
)

VIDEO_NOT_FOUND = EmbedDict(
title='Video not found',
color=DARK_RED
)
31 changes: 31 additions & 0 deletions Spoyt/env_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
from os import environ, getenv

from Spoyt.logging import log


def current_platform() -> str:
return getenv('PLATFORM', 'unknown')


def is_discord() -> bool:
return current_platform() == 'discord'


def is_guilded() -> bool:
return current_platform() == 'guilded'


def check_platform(source: str, platform: str) -> bool:
if source.lower().endswith(platform.lower()):
environ['PLATFORM'] = platform
log.info(f'Automatically set "PLATFORM" to "{platform}"')
return True
return False


def auto_set_platform(source: str) -> bool:
for platform in ['guilded', 'discord']:
if check_platform(source, platform):
return True
return False
4 changes: 4 additions & 0 deletions Spoyt/logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from logging import getLogger

log = getLogger('rich')
6 changes: 6 additions & 0 deletions Spoyt/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from os import getenv


def bot_token():
return getenv('BOT_TOKEN')
Loading

0 comments on commit ac9a5ed

Please sign in to comment.