Compare commits

...

13 Commits

8 changed files with 354 additions and 176 deletions

1
.cache Normal file
View File

@ -0,0 +1 @@
{"access_token": "BQAGTFRSU7DFvo3kw6g54KbXF0l1tjg2R1CDfGi9pPJayKEZTIuo61BvycbXt_HOHlnpCTNTaf7k7xfpv2SrAD3_su1ZyWoU0lel31k-6fDO2lu9P896", "token_type": "Bearer", "expires_in": 3600, "expires_at": 1680722492}

View File

@ -10,9 +10,8 @@ python-telegram-bot = "*"
requests = "*" requests = "*"
spotipy = "*" spotipy = "*"
dpath = "*" dpath = "*"
gmusicapi = "*"
pathlib = "*" pathlib = "*"
uuid = "*" uuid = "*"
[requires] [requires]
python_version = "3.6" python_version = "3.10"

256
Pipfile.lock generated Normal file
View File

@ -0,0 +1,256 @@
{
"_meta": {
"hash": {
"sha256": "2377889f39de218eaf9ff088a0ea36e1476097729d0ac372f67bfeb794d82b10"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.10"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"anyio": {
"hashes": [
"sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421",
"sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3"
],
"markers": "python_full_version >= '3.6.2'",
"version": "==3.6.2"
},
"async-timeout": {
"hashes": [
"sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15",
"sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"
],
"markers": "python_full_version <= '3.11.2'",
"version": "==4.0.2"
},
"certifi": {
"hashes": [
"sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3",
"sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"
],
"markers": "python_version >= '3.6'",
"version": "==2022.12.7"
},
"charset-normalizer": {
"hashes": [
"sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6",
"sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1",
"sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e",
"sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373",
"sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62",
"sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230",
"sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be",
"sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c",
"sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0",
"sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448",
"sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f",
"sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649",
"sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d",
"sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0",
"sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706",
"sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a",
"sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59",
"sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23",
"sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5",
"sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb",
"sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e",
"sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e",
"sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c",
"sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28",
"sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d",
"sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41",
"sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974",
"sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce",
"sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f",
"sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1",
"sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d",
"sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8",
"sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017",
"sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31",
"sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7",
"sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8",
"sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e",
"sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14",
"sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd",
"sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d",
"sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795",
"sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b",
"sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b",
"sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b",
"sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203",
"sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f",
"sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19",
"sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1",
"sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a",
"sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac",
"sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9",
"sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0",
"sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137",
"sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f",
"sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6",
"sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5",
"sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909",
"sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f",
"sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0",
"sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324",
"sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755",
"sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb",
"sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854",
"sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c",
"sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60",
"sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84",
"sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0",
"sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b",
"sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1",
"sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531",
"sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1",
"sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11",
"sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326",
"sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df",
"sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"
],
"markers": "python_full_version >= '3.7.0'",
"version": "==3.1.0"
},
"dpath": {
"hashes": [
"sha256:559edcbfc806ca2f9ad9e63566f22e5d41c000e4215bbce9dbf1ca4c859f5e0b",
"sha256:ccd964db839baad4aa820612b4b8731b09f40a245d401b723156ce4ef45b22b7"
],
"index": "pypi",
"version": "==2.1.5"
},
"h11": {
"hashes": [
"sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d",
"sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"
],
"markers": "python_version >= '3.7'",
"version": "==0.14.0"
},
"httpcore": {
"hashes": [
"sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb",
"sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"
],
"markers": "python_version >= '3.7'",
"version": "==0.16.3"
},
"httpx": {
"hashes": [
"sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9",
"sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"
],
"markers": "python_version >= '3.7'",
"version": "==0.23.3"
},
"idna": {
"hashes": [
"sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4",
"sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"
],
"markers": "python_version >= '3.5'",
"version": "==3.4"
},
"pathlib": {
"hashes": [
"sha256:6940718dfc3eff4258203ad5021090933e5c04707d5ca8cc9e73c94a7894ea9f",
"sha256:f35f95ab8b0f59e6d354090350b44a80a80635d22efdedfa84c7ad1cf0a74147"
],
"index": "pypi",
"version": "==1.0.1"
},
"python-telegram-bot": {
"hashes": [
"sha256:4d1d4b643ce158aa17a0987b84005eaf25fe0ce8b38fd234099594985611c198",
"sha256:d0aa53e1f06d7cb7919cc0e2d6c81a02d968fc29921aeaa962edd1efb816a9bd"
],
"index": "pypi",
"version": "==20.2"
},
"redis": {
"hashes": [
"sha256:2c19e6767c474f2e85167909061d525ed65bea9301c0770bb151e041b7ac89a2",
"sha256:73ec35da4da267d6847e47f68730fdd5f62e2ca69e3ef5885c6a78a9374c3893"
],
"markers": "python_version >= '3.7'",
"version": "==4.5.4"
},
"requests": {
"hashes": [
"sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa",
"sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"
],
"index": "pypi",
"version": "==2.28.2"
},
"rfc3986": {
"extras": [
"idna2008"
],
"hashes": [
"sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835",
"sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"
],
"version": "==1.5.0"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0"
},
"sniffio": {
"hashes": [
"sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101",
"sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"
],
"markers": "python_version >= '3.7'",
"version": "==1.3.0"
},
"spotipy": {
"hashes": [
"sha256:1dac15ac0aaf5246461a3cb0b3d837bc7af7b78597441289b500a5abac9fe9c4",
"sha256:54680dbf243a2b0cff0e591e1d269692e94265273b52ab90994a661555c04ac7",
"sha256:aa023d8bc606053d95e8961f52293fdd8cd12ef4fad8f829e701bb3d61c48d76"
],
"index": "pypi",
"version": "==2.22.1"
},
"urllib3": {
"hashes": [
"sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305",
"sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
"version": "==1.26.15"
},
"uuid": {
"hashes": [
"sha256:1f87cc004ac5120466f36c5beae48b4c48cc411968eed0eaecd3da82aa96193f"
],
"index": "pypi",
"version": "==1.30"
},
"ytmusicapi": {
"hashes": [
"sha256:3d47a8803dceeb0289c7cf29a0317c5d6051d0b7c28fda067f6abb001746f7ac",
"sha256:aa3165100ff5c0e1f49f9a046312f878c31eea83fde14af0707e3368ae923fe4"
],
"index": "pypi",
"version": "==0.25.2"
}
},
"develop": {}
}

Binary file not shown.

Binary file not shown.

260
music.py Executable file → Normal file
View File

@ -1,221 +1,137 @@
import logging
from tbotconfig import * from tbotconfig import *
# Telegram things: # Telegram things:
#from telegram import InlineKeyboardButton, InlineKeyboardMarkup from telegram import InlineQueryResultArticle, InputTextMessageContent, Update
from telegram import InlineKeyboardMarkup, InlineKeyboardButton, InlineQueryResultArticle, InputTextMessageContent, InlineQueryResult, InlineQueryResultAudio from telegram.constants import ParseMode
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackQueryHandler, ConversationHandler, InlineQueryHandler, ChosenInlineResultHandler, CallbackContext from telegram.ext import Application, CommandHandler, ContextTypes, InlineQueryHandler
# Other needful stuff # Other needful stuff
import asyncio
import html
import json
import logging
import traceback
from uuid import uuid4 from uuid import uuid4
import urllib.request import urllib.request
import urllib import urllib
import re import re
import spotipy import spotipy
import spotipy.oauth2 import spotipy.oauth2
import json from dpath import util
import dpath
import requests import requests
import time import time
from gmusicapi import Mobileclient
import os import os
from pathlib import Path from pathlib import Path
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO
)
#Configure how many results to fetch
num_results = 5
# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
logger = logging.getLogger(__name__)
# Spotify:
spotify_credentials = spotipy.oauth2.SpotifyClientCredentials(SPOTIPY_CLIENT_ID, SPOTIPY_CLIENT_SECRET)
sp = spotipy.Spotify(client_credentials_manager=spotify_credentials)
def ask_for_credentials():
# Make an instance of the api and attempts to login with it.
# Return the authenticated api.
# We're not going to upload anything, so the Mobileclient is what we want.
gpm = Mobileclient()
logged_in = False
attempts = 0
while not logged_in and attempts < 3:
logged_in = gpm.oauth_login(Mobileclient.FROM_MAC_ADDRESS, oauth_credentials=u'./gpmlogin.json')
attempts += 1
return gpm
#
# Actual bot stuffs # Actual bot stuffs
# #
# Define a few command handlers. These usually take the two arguments bot and update. Error handlers also receive the raised TelegramError object in error. # Define a few command handlers. These usually take the two arguments bot and update. Error handlers also receive the raised TelegramError object in error.
def start(update, context: CallbackContext):
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Send a message when the command /start is issued.""" """Send a message when the command /start is issued."""
update.message.reply_text('Hello there!\n/help will give a short introduction to this bot.\nIts an inline bot, so you shouldn\'nt really be using it here.\nThis is a bot made by @DailytheNoob, check out the code on daviddaily.dev/david/telegram-music-bot') await context.bot.send_message(
chat_id=update.effective_chat.id,
text="'Hello there!\n/help will give a short introduction to this bot.\nIts an inline bot, so you shouldn\'nt really be using it here.\nThis is a bot made by @DailytheNoob, check out the code on daviddaily.dev/david/telegram-music-bot'"
)
def help(update, context: CallbackContext):
async def help(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Send a message when the command /help is issued.""" """Send a message when the command /help is issued."""
update.message.reply_markdown(f"Attention! I am an inline bot only!\n\nStart your message with @MusicServiceBot and then the name of the song you want me to search spotify for. Wait for a few seconds and you should get {num_results} results back.\nIf spotify provides a preview for the song, when you tap the correct result you'll get a 30 second preview for the song, otherwise its just the name of the song. Once you pick the right result you'll get a button that says `Show links`. When you click on this it'll search GPM and Youtube for the song and will show the links.\n*This takes a bit, please be patient. If you wait more than 3 days, the button probably won't work. To fix that please search again.*") await context.bot.update.message.reply_markdown_v2(f"Attention! I am an inline bot only!\n\nStart your message with @MusicServiceBot and then the name of the song you want me to search spotify for. Wait for a few seconds and you should get {num_results} results back.\nIf spotify provides a preview for the song, when you tap the desired result you'll get a 30 second preview for the song, otherwise its just the name of the song. Once you pick the right result you'll get a button for Spotify and more links that goes to a link aggregation site that will have links to most other services.")
def inlinequery(update, context: CallbackContext): async def inline_query(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Handle the inline query. This is run when you type: @botusername <query>"""
query = update.inline_query.query query = update.inline_query.query
print(query)
query_id = uuid4()
if query == "":
return
results = [] results = []
spotify_credentials = spotipy.oauth2.SpotifyClientCredentials(SPOTIPY_CLIENT_ID, SPOTIPY_CLIENT_SECRET) sp_info = sp_search(query)
sp = spotipy.Spotify(client_credentials_manager=spotify_credentials)
if query:
sp_info = sp.search(q=query, limit=num_results)
open(f"./queries/{query_id}.json", 'w+').write(json.dumps(sp_info, indent = 4))
for i in range(num_results):
try:
dpath.util.get(sp_info, f"/tracks/items/[{i}]/name")
except:
continue
else:
sp_title = dpath.util.get(sp_info, f"/tracks/items/[{i}]/name")
sp_artist = dpath.util.get(sp_info, f"/tracks/items/[{i}]/artists/[0]/name")
sp_albname = dpath.util.get(sp_info, f"/tracks/items/[{i}]/album/name")
sp_albdate = dpath.util.get(sp_info, f"/tracks/items/[{i}]/album/release_date")
sp_art = dpath.util.get(sp_info, f"/tracks/items/[{i}]/album/images/[2]/url")
sp_audio = dpath.util.get(sp_info, f"/tracks/items/[{i}]/preview_url")
callback_data = f"query_id:<{query_id}>result:<{i}>"
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("Show links", callback_data=callback_data)]])
description = f"By {sp_artist} on the album {sp_albname}, released {sp_albdate}" for i in range(len(sp_info)):
"""Spotify"""
sp_title = util.get(sp_info, f"/tracks/items/[{i}]/name")
sp_artist = util.get(sp_info, f"/tracks/items/[{i}]/artists/[0]/name")
sp_albname = util.get(sp_info, f"/tracks/items/[{i}]/album/name")
sp_albdate = util.get(sp_info, f"/tracks/items/[{i}]/album/release_date")
sp_art = util.get(sp_info, f"/tracks/items/[{i}]/album/images/[2]/url")
sp_audio = util.get(sp_info, f"/tracks/items/[{i}]/preview_url")
sp_link = util.get(sp_info, f"/tracks/items/[{i}]/external_urls/spotify")
songlink = "https://song.link/{0}".format(sp_link)
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("Spotify", url = sp_link), InlineKeyboardButton("More", url = songlink)]])
description = f"By {sp_artist} on the album {sp_albname}, released {sp_albdate}"
if "None" in str(sp_audio): if "None" in str(sp_audio):
message_content = f"Check out \"{sp_title}\" by {sp_artist} on the album \"{sp_albname}\"" message_content = f"Check out \"{sp_title}\" by {sp_artist} on the album \"{sp_albname}\""
results.append(InlineQueryResultArticle(id = i, title = sp_title, description = description, input_message_content = InputTextMessageContent(message_content), thumb_url = sp_art, reply_markup = reply_markup),) results.append(InlineQueryResultArticle(id = i, title = sp_title, description = description, input_message_content = InputTextMessageContent(message_content), thumb_url = sp_art, reply_markup = reply_markup),)
else: else:
message_content = f"Listen to \"{sp_title}\" by {sp_artist} on the album \"{sp_albname}\"" message_content = f"Listen to \"{sp_title}\" by {sp_artist} on the album \"{sp_albname}\""
results.append(InlineQueryResultAudio(id = i, audio_url = sp_audio, title = sp_title, performer = sp_artist, audio_duration = 30, caption = message_content, reply_markup = reply_markup),) results.append(InlineQueryResultAudio(id = i, audio_url = sp_audio, title = sp_title, performer = sp_artist, audio_duration = 30, caption = message_content, reply_markup = reply_markup),)
open(f"./queries/{query_id}.json", 'w+').write(json.dumps(sp_info, indent = 4))
update.inline_query.answer(results) update.inline_query.answer(results)
def button(update, context: CallbackContext): async def sp_search(query):
query = update.callback_query return sp.search(q=query, limit=num_results)
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("Loading links, please wait", url='https://www.youtube.com/watch?v=rTga41r3a4s')]])
query.edit_message_reply_markup(reply_markup=reply_markup)
query_id = re.search('(?<=query_id:\<).*(?=\>result)', f"{query.data}") # matches everything between query_id:< and >result
query_id = str(query_id.group(0))
result_chosen = re.search('(?<=result:\<).', f"{query.data}") # matches one character after result:< async def error_handler(update) -> None:
result_chosen = str(result_chosen.group(0)) """Log the error and send a telegram message to notify the developer."""
# Log the error before we do anything else, so we can see it even if something breaks.
data_file = Path(f"./queries/{query_id}.json") logger.error(msg="Exception while handling an update:", exc_info=context.error)
if not data_file.is_file():
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("Request not found, probably over 3 days old. Please start over.", url='https://www.youtube.com/watch?v=dQw4w9WgXcQ')]])
query.edit_message_reply_markup(reply_markup=reply_markup)
return
with open(f"./queries/{query_id}.json", encoding='utf-8') as data_file:
sp_info = json.loads(data_file.read())
sp_link = dpath.util.get(sp_info, f"/tracks/items/[{result_chosen}]/external_urls/spotify") # This can be your own ID, or one for a developer group/channel.
sp_title = dpath.util.get(sp_info, f"/tracks/items/[{result_chosen}]/name") # You can use the /start command of this bot to see your chat id.
sp_artist = dpath.util.get(sp_info, f"/tracks/items/[{result_chosen}]/artists/[0]/name") DEVELOPER_CHAT_ID = 175042676
sp_albname = dpath.util.get(sp_info, f"/tracks/items/[{result_chosen}]/album/name") # traceback.format_exception returns the usual python message about an exception, but as a
sp_art = dpath.util.get(sp_info, f"/tracks/items/[{result_chosen}]/album/images/[2]/url") # list of strings rather than a single string, so we have to join them together.
tb_list = traceback.format_exception(None, context.error, context.error.__traceback__)
songlink = "https://song.link/{0}".format(sp_link) tb_string = ''.join(tb_list)
gpm = ask_for_credentials()
if not gpm.is_authenticated():
print("\n\nGPM fucked up somewhere\n\n")
gpm = Mobileclient(debug_logging=False)
gpm.oauth_login(Mobileclient.FROM_MAC_ADDRESS, oauth_credentials=u'./gpmlogin.json')
gpm_results = gpm.search(f"{sp_title} by {sp_artist} on {sp_albname}", max_results=1)
gpm.logout()
try: # Build the message with some markup and additional information about what happened.
dpath.util.get(gpm_results, '/song_hits/[0]/track/nid') # You might need to add some logic to deal with messages longer than the 4096 character limit.
except KeyError: message = (
gpm_link = False f'An exception was raised while handling an update\n'
yt_link = False f'<pre>update = {html.escape(json.dumps(update.to_dict(), indent=2, ensure_ascii=False))}'
else: '</pre>\n\n'
gpm_link = dpath.util.get(gpm_results, '/song_hits/[0]/track/nid') f'<pre>context.chat_data = {html.escape(str(context.chat_data))}</pre>\n\n'
gpm_link = f"https://play.google.com/music/m/T{gpm_link}" f'<pre>context.user_data = {html.escape(str(context.user_data))}</pre>\n\n'
try: f'<pre>{html.escape(tb_string)}</pre>'
dpath.util.get(gpm_results, '/video_hits/[0]/youtube_video/id') )
except KeyError:
yt_link = False
else:
yt_link = dpath.util.get(gpm_results, '/video_hits/[0]/youtube_video/id')
yt_link = f"https://www.youtube.com/watch?v={yt_link}"
if not yt_link: # Finally, send the message
query_string = urllib.parse.urlencode({"search_query" : f"{sp_title} {sp_artist}"}) context.bot.send_message(chat_id=DEVELOPER_CHAT_ID, text=message, parse_mode=ParseMode.HTML)
html_content = urllib.request.urlopen(f"http://www.youtube.com/results?{query_string}")
search_results = re.findall(r'href=\"\/watch\?v=(.{11})', html_content.read().decode())
yt_link = f"http://www.youtube.com/watch?v={search_results[0]}"
if gpm_link:
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("Spotify", url = sp_link), InlineKeyboardButton("GPM", url = gpm_link), InlineKeyboardButton("YouTube", url = yt_link), InlineKeyboardButton("More", url = songlink)]])
if not gpm_link:
reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("Spotify", url = sp_link), InlineKeyboardButton("YouTube", url = yt_link), InlineKeyboardButton("More", url = songlink)]])
query.edit_message_reply_markup(reply_markup=reply_markup)
os.system('find ./queries -mtime +3 -type f -delete')
def main() -> None:
#Configure how many results to fetch
num_results = 5
def error(update, context: CallbackContext): # Spotify:
# Log Errors caused by Updates spotify_credentials = spotipy.oauth2.SpotifyClientCredentials(SPOTIPY_CLIENT_ID, SPOTIPY_CLIENT_SECRET)
logger.warning(f"\nUpdate {update} caused error {context.error}\n") sp = spotipy.Spotify(client_credentials_manager=spotify_credentials)
# Create the Application and pass it your bot's token.
def main(): application = Application.builder().token(BOT_TOKEN).build()
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater(TBOT_TOKEN, use_context=True)
# Get the dispatcher to register handlers
bot = updater.dispatcher
# on different commands - answer in Telegram # on different commands - answer in Telegram
bot.add_handler(CommandHandler("start", start)) application.add_handler(CommandHandler("start", start))
bot.add_handler(CommandHandler("help", help)) application.add_handler(CommandHandler("help", help))
# on noncommand i.e message - echo the message on Telegram # on non command i.e message - echo the message on Telegram
bot.add_handler(InlineQueryHandler(inlinequery)) application.add_handler(InlineQueryHandler(inline_query))
bot.add_handler(CallbackQueryHandler(button)) # Run the bot until the user presses Ctrl-C
application.run_polling()
# log all errors
bot.add_error_handler(error)
# Start the Bot
updater.start_polling()
# Block until the user presses Ctrl-C or the process receives SIGINT,
# SIGTERM or SIGABRT. This should be used most of the time, since
# start_polling() is non-blocking and will stop the bot gracefully.
updater.idle()
if __name__ == '__main__': if __name__ == "__main__":
main() main()

6
tbotconfig.py Normal file
View File

@ -0,0 +1,6 @@
# Spotify:
SPOTIPY_CLIENT_ID = 'cd2fc36d8c4b4c25b2a1fa3d5c764e9e'
SPOTIPY_CLIENT_SECRET = '1886bb3b219342bda49a0c7bbb60a07e'
BOT_TOKEN = '698031045:AAFuWqNZcum4wTQKQtZJsP4YyId_njsDAvA'
print('Access tokens imported, ready to go.\n\n')

View File

@ -7,8 +7,8 @@ Group=david
Restart=always Restart=always
RestartSec=10 RestartSec=10
Type=default Type=default
WorkingDirectory=/path/to/working/dir WorkingDirectory=/home/david/tmusic
ExecStart=/path/to/pipenv/virtualenv/python3 music.py ExecStart=/home/david/.local/share/virtualenvs/tmusic-l3mWxOyb/bin/python3 music.py
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target