PandaAPI 1.0.7__tar.gz → 1.0.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PandaAPI
3
- Version: 1.0.7
3
+ Version: 1.0.9
4
4
  Summary: Python utility hub by @ll_PANDA_BBY_ll
5
5
  Author: PANDA
6
6
  Author-email:
@@ -53,14 +53,23 @@ print(mail["email"])
53
53
  inbox = api.temp_mail_inbox(mail["sid_token"])
54
54
  if inbox["emails"]:
55
55
  msg = api.temp_mail_read(mail["sid_token"], inbox["emails"][0]["id"])
56
- print(msg["otp_codes"]) # extracted OTP codes
57
- print(msg["verify_links"]) # extracted verification links
56
+ print(msg["otp_codes"]) # extracted OTP codes
57
+ print(msg["verify_links"]) # extracted verification links
58
58
 
59
59
  # Fake Identity
60
- print(api.fake_identity("IN")) # Indian fake identity
60
+ print(api.fake_identity("IN")) # Indian fake identity
61
61
 
62
- # Lyrics
63
- print(api.lyrics("Kesariya", "Arijit Singh"))
62
+ # Media — YouTube
63
+ results = api.yt_search("Kesariya Arijit Singh")
64
+ print(results[0]["title"])
65
+ print(results[0]["url"])
66
+ print(api.yt_thumb(results[0]["id"]))
67
+
68
+ # Media — Lyrics (synced timestamps supported)
69
+ song = api.lyrics("Arijit Singh", "Tum Hi Ho")
70
+ print(song["lyrics"])
71
+ print(song["synced"]) # True = has [mm:ss] timestamps
72
+ print(song["source"]) # lyrics.ovh or lrclib.net
64
73
 
65
74
  # AI
66
75
  print(api.gemini("Hello!"))
@@ -74,11 +83,11 @@ print(api.chatgpt("Explain black holes"))
74
83
  | `tools` | `password`, `morse_encode`, `morse_decode`, `github`, `pypi`, `hashtag`, `chatbot`, `meme`, `unsplash`, `imdb`, `leetcode`, `bhagwatgita` |
75
84
  | `ai` | `gemini`, `chatgpt`, `blackbox` |
76
85
  | `telegram` | `tg_bot_info`, `tg_user` |
77
- | `media` | `yt_search`, `yt_thumb` |
86
+ | `media` | `yt_search`, `yt_thumb`, `lyrics` |
78
87
  | `osint` | `ip_lookup`, `phone_lookup`, `email_verify`, `username_search`, `breach_check`, `whois`, `dns_lookup`, `ssl_info`, `exif_read` |
79
88
  | `crypto` | `b64_encode`, `b64_decode`, `md5`, `sha256`, `sha512`, `rot13`, `caesar`, `xor_encrypt`, `xor_decrypt`, `jwt_decode` |
80
89
  | `network` | `ping`, `port_scan`, `headers`, `ssl_check`, `torcheck`, `reverse_ip`, `subdomain_scan` |
81
- | `dark` | `fake_identity`, `temp_mail_create`, `temp_mail_inbox`, `temp_mail_read`, `dark_joke`, `lyrics` |
90
+ | `dark` | `fake_identity`, `temp_mail_create`, `temp_mail_inbox`, `temp_mail_read`, `dark_joke` |
82
91
 
83
92
  ## License
84
93
 
@@ -178,3 +178,4 @@ class PandaAPI:
178
178
 
179
179
 
180
180
  api = PandaAPI()
181
+ from .modules.media import lyrics
@@ -105,80 +105,3 @@ def dark_joke() -> dict:
105
105
  return {"success": False, "error": str(e)}
106
106
 
107
107
 
108
- def lyrics(song: str, artist: str = "") -> dict:
109
- try:
110
- query = f"{artist} {song}".strip()
111
- headers = {
112
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
113
- }
114
-
115
- # Method 1: lyrics.ovh (English songs)
116
- if artist:
117
- r = requests.get(
118
- f"https://api.lyrics.ovh/v1/{requests.utils.quote(artist)}/{requests.utils.quote(song)}",
119
- timeout=10,
120
- )
121
- if r.status_code == 200:
122
- lyr = r.json().get("lyrics", "")
123
- if lyr:
124
- return {"song": song, "artist": artist, "lyrics": lyr, "source": "lyrics.ovh", "success": True}
125
-
126
- # Method 2: Genius search scrape
127
- search_r = requests.get(
128
- f"https://api.genius.com/search?q={requests.utils.quote(query)}",
129
- headers={**headers, "Authorization": "Bearer alXE5K2_D2ZJVMWKW7pWAbsOaOFWlEAzHmDNJY3CyGRTMh5z3HKFqSBJaWrHK2T9"},
130
- timeout=10,
131
- )
132
- if search_r.status_code == 200:
133
- hits = search_r.json().get("response", {}).get("hits", [])
134
- if hits:
135
- top = hits[0]["result"]
136
- song_title = top.get("title", song)
137
- artist_name = top.get("primary_artist", {}).get("name", artist)
138
- song_url = top.get("url", "")
139
- # scrape lyrics from genius page
140
- page = requests.get(song_url, headers=headers, timeout=10)
141
- from bs4 import BeautifulSoup
142
- soup = BeautifulSoup(page.text, "html.parser")
143
- # remove scripts
144
- for s in soup.find_all("script"):
145
- s.decompose()
146
- containers = soup.find_all("div", attrs={"data-lyrics-container": "true"})
147
- if containers:
148
- lyr_parts = []
149
- for c in containers:
150
- for br in c.find_all("br"):
151
- br.replace_with("\n")
152
- lyr_parts.append(c.get_text())
153
- lyr = "\n".join(lyr_parts).strip()
154
- return {
155
- "song": song_title,
156
- "artist": artist_name,
157
- "lyrics": lyr,
158
- "genius_url": song_url,
159
- "source": "genius",
160
- "success": True,
161
- }
162
-
163
- # Method 3: lyrics.ovh suggest fallback
164
- rs = requests.get(
165
- f"https://api.lyrics.ovh/suggest/{requests.utils.quote(query)}",
166
- timeout=10,
167
- ).json()
168
- results = rs.get("data", [])
169
- if results:
170
- top = results[0]
171
- artist_name = top.get("artist", {}).get("name", "")
172
- title = top.get("title", "")
173
- r2 = requests.get(
174
- f"https://api.lyrics.ovh/v1/{requests.utils.quote(artist_name)}/{requests.utils.quote(title)}",
175
- timeout=10,
176
- )
177
- if r2.status_code == 200:
178
- lyr = r2.json().get("lyrics", "")
179
- if lyr:
180
- return {"song": title, "artist": artist_name, "lyrics": lyr, "source": "lyrics.ovh", "success": True}
181
-
182
- return {"success": False, "error": "Lyrics not found — try English song name or add artist name"}
183
- except Exception as e:
184
- return {"success": False, "error": str(e)}
@@ -0,0 +1,138 @@
1
+ import requests
2
+
3
+
4
+ def yt_search(query: str) -> list:
5
+ try:
6
+ import yt_dlp
7
+ ydl_opts = {
8
+ "quiet": True,
9
+ "skip_download": True,
10
+ "extract_flat": True,
11
+ }
12
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
13
+ info = ydl.extract_info(f"ytsearch5:{query}", download=False)
14
+ entries = info.get("entries", [])
15
+ return [
16
+ {
17
+ "title": e.get("title"),
18
+ "url": f"https://youtube.com/watch?v={e.get('id')}",
19
+ "duration": e.get("duration"),
20
+ "channel": e.get("channel"),
21
+ "id": e.get("id"),
22
+ }
23
+ for e in entries
24
+ ]
25
+ except ImportError:
26
+ return [{"error": "yt_dlp not installed", "success": False}]
27
+
28
+
29
+ def yt_thumb(video_id: str) -> str:
30
+ return f"https://img.youtube.com/vi/{video_id}/maxresdefault.jpg"
31
+
32
+
33
+ def lyrics(artist: str, title: str) -> dict:
34
+ try:
35
+ url = f"https://api.lyrics.ovh/v1/{artist}/{title}"
36
+ r = requests.get(url, timeout=8)
37
+ if r.status_code == 200:
38
+ data = r.json()
39
+ if data.get("lyrics"):
40
+ return {
41
+ "success": True,
42
+ "artist": artist,
43
+ "title": title,
44
+ "lyrics": data["lyrics"],
45
+ "synced": False,
46
+ "source": "lyrics.ovh",
47
+ }
48
+ except Exception:
49
+ pass
50
+
51
+ try:
52
+ url = "https://lrclib.net/api/get"
53
+ params = {"artist_name": artist, "track_name": title}
54
+ r = requests.get(url, params=params, timeout=8)
55
+ if r.status_code == 200:
56
+ data = r.json()
57
+ synced = data.get("syncedLyrics")
58
+ plain = data.get("plainLyrics")
59
+ if synced or plain:
60
+ return {
61
+ "success": True,
62
+ "artist": artist,
63
+ "title": title,
64
+ "lyrics": synced or plain,
65
+ "synced": bool(synced),
66
+ "source": "lrclib.net",
67
+ }
68
+ except Exception:
69
+ pass
70
+
71
+ return {"success": False, "error": "Lyrics not found on any source"}
72
+
73
+
74
+ def lyrics(song: str, artist: str = "") -> dict:
75
+ import requests
76
+ query = f"{artist} {song}".strip()
77
+
78
+ # Method 1: lyrics.ovh
79
+ try:
80
+ if artist:
81
+ r = requests.get(
82
+ f"https://api.lyrics.ovh/v1/{requests.utils.quote(artist)}/{requests.utils.quote(song)}",
83
+ timeout=8
84
+ )
85
+ if r.status_code == 200:
86
+ lyr = r.json().get("lyrics", "")
87
+ if lyr:
88
+ return {"song": song, "artist": artist, "lyrics": lyr, "source": "lyrics.ovh", "success": True}
89
+ except Exception:
90
+ pass
91
+
92
+ # Method 2: lrclib.net
93
+ try:
94
+ r = requests.get(
95
+ "https://lrclib.net/api/search",
96
+ params={"q": query},
97
+ timeout=8
98
+ )
99
+ if r.status_code == 200:
100
+ results = r.json()
101
+ if results:
102
+ best = results[0]
103
+ lyr = best.get("syncedLyrics") or best.get("plainLyrics")
104
+ if lyr:
105
+ return {
106
+ "song": best.get("trackName", song),
107
+ "artist": best.get("artistName", artist),
108
+ "lyrics": lyr,
109
+ "synced": bool(best.get("syncedLyrics")),
110
+ "source": "lrclib.net",
111
+ "success": True
112
+ }
113
+ except Exception:
114
+ pass
115
+
116
+ # Method 3: lyrics.ovh suggest fallback
117
+ try:
118
+ r = requests.get(
119
+ f"https://api.lyrics.ovh/suggest/{requests.utils.quote(query)}",
120
+ timeout=8
121
+ )
122
+ if r.status_code == 200:
123
+ data = r.json().get("data", [])
124
+ if data:
125
+ artist_name = data[0]["artist"]["name"]
126
+ title = data[0]["title"]
127
+ r2 = requests.get(
128
+ f"https://api.lyrics.ovh/v1/{requests.utils.quote(artist_name)}/{requests.utils.quote(title)}",
129
+ timeout=8
130
+ )
131
+ if r2.status_code == 200:
132
+ lyr = r2.json().get("lyrics", "")
133
+ if lyr:
134
+ return {"song": title, "artist": artist_name, "lyrics": lyr, "source": "lyrics.ovh", "success": True}
135
+ except Exception:
136
+ pass
137
+
138
+ return {"success": False, "error": "Lyrics not found on any source"}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PandaAPI
3
- Version: 1.0.7
3
+ Version: 1.0.9
4
4
  Summary: Python utility hub by @ll_PANDA_BBY_ll
5
5
  Author: PANDA
6
6
  Author-email:
@@ -53,14 +53,23 @@ print(mail["email"])
53
53
  inbox = api.temp_mail_inbox(mail["sid_token"])
54
54
  if inbox["emails"]:
55
55
  msg = api.temp_mail_read(mail["sid_token"], inbox["emails"][0]["id"])
56
- print(msg["otp_codes"]) # extracted OTP codes
57
- print(msg["verify_links"]) # extracted verification links
56
+ print(msg["otp_codes"]) # extracted OTP codes
57
+ print(msg["verify_links"]) # extracted verification links
58
58
 
59
59
  # Fake Identity
60
- print(api.fake_identity("IN")) # Indian fake identity
60
+ print(api.fake_identity("IN")) # Indian fake identity
61
61
 
62
- # Lyrics
63
- print(api.lyrics("Kesariya", "Arijit Singh"))
62
+ # Media — YouTube
63
+ results = api.yt_search("Kesariya Arijit Singh")
64
+ print(results[0]["title"])
65
+ print(results[0]["url"])
66
+ print(api.yt_thumb(results[0]["id"]))
67
+
68
+ # Media — Lyrics (synced timestamps supported)
69
+ song = api.lyrics("Arijit Singh", "Tum Hi Ho")
70
+ print(song["lyrics"])
71
+ print(song["synced"]) # True = has [mm:ss] timestamps
72
+ print(song["source"]) # lyrics.ovh or lrclib.net
64
73
 
65
74
  # AI
66
75
  print(api.gemini("Hello!"))
@@ -74,11 +83,11 @@ print(api.chatgpt("Explain black holes"))
74
83
  | `tools` | `password`, `morse_encode`, `morse_decode`, `github`, `pypi`, `hashtag`, `chatbot`, `meme`, `unsplash`, `imdb`, `leetcode`, `bhagwatgita` |
75
84
  | `ai` | `gemini`, `chatgpt`, `blackbox` |
76
85
  | `telegram` | `tg_bot_info`, `tg_user` |
77
- | `media` | `yt_search`, `yt_thumb` |
86
+ | `media` | `yt_search`, `yt_thumb`, `lyrics` |
78
87
  | `osint` | `ip_lookup`, `phone_lookup`, `email_verify`, `username_search`, `breach_check`, `whois`, `dns_lookup`, `ssl_info`, `exif_read` |
79
88
  | `crypto` | `b64_encode`, `b64_decode`, `md5`, `sha256`, `sha512`, `rot13`, `caesar`, `xor_encrypt`, `xor_decrypt`, `jwt_decode` |
80
89
  | `network` | `ping`, `port_scan`, `headers`, `ssl_check`, `torcheck`, `reverse_ip`, `subdomain_scan` |
81
- | `dark` | `fake_identity`, `temp_mail_create`, `temp_mail_inbox`, `temp_mail_read`, `dark_joke`, `lyrics` |
90
+ | `dark` | `fake_identity`, `temp_mail_create`, `temp_mail_inbox`, `temp_mail_read`, `dark_joke` |
82
91
 
83
92
  ## License
84
93
 
@@ -33,14 +33,23 @@ print(mail["email"])
33
33
  inbox = api.temp_mail_inbox(mail["sid_token"])
34
34
  if inbox["emails"]:
35
35
  msg = api.temp_mail_read(mail["sid_token"], inbox["emails"][0]["id"])
36
- print(msg["otp_codes"]) # extracted OTP codes
37
- print(msg["verify_links"]) # extracted verification links
36
+ print(msg["otp_codes"]) # extracted OTP codes
37
+ print(msg["verify_links"]) # extracted verification links
38
38
 
39
39
  # Fake Identity
40
- print(api.fake_identity("IN")) # Indian fake identity
40
+ print(api.fake_identity("IN")) # Indian fake identity
41
41
 
42
- # Lyrics
43
- print(api.lyrics("Kesariya", "Arijit Singh"))
42
+ # Media — YouTube
43
+ results = api.yt_search("Kesariya Arijit Singh")
44
+ print(results[0]["title"])
45
+ print(results[0]["url"])
46
+ print(api.yt_thumb(results[0]["id"]))
47
+
48
+ # Media — Lyrics (synced timestamps supported)
49
+ song = api.lyrics("Arijit Singh", "Tum Hi Ho")
50
+ print(song["lyrics"])
51
+ print(song["synced"]) # True = has [mm:ss] timestamps
52
+ print(song["source"]) # lyrics.ovh or lrclib.net
44
53
 
45
54
  # AI
46
55
  print(api.gemini("Hello!"))
@@ -54,11 +63,11 @@ print(api.chatgpt("Explain black holes"))
54
63
  | `tools` | `password`, `morse_encode`, `morse_decode`, `github`, `pypi`, `hashtag`, `chatbot`, `meme`, `unsplash`, `imdb`, `leetcode`, `bhagwatgita` |
55
64
  | `ai` | `gemini`, `chatgpt`, `blackbox` |
56
65
  | `telegram` | `tg_bot_info`, `tg_user` |
57
- | `media` | `yt_search`, `yt_thumb` |
66
+ | `media` | `yt_search`, `yt_thumb`, `lyrics` |
58
67
  | `osint` | `ip_lookup`, `phone_lookup`, `email_verify`, `username_search`, `breach_check`, `whois`, `dns_lookup`, `ssl_info`, `exif_read` |
59
68
  | `crypto` | `b64_encode`, `b64_decode`, `md5`, `sha256`, `sha512`, `rot13`, `caesar`, `xor_encrypt`, `xor_decrypt`, `jwt_decode` |
60
69
  | `network` | `ping`, `port_scan`, `headers`, `ssl_check`, `torcheck`, `reverse_ip`, `subdomain_scan` |
61
- | `dark` | `fake_identity`, `temp_mail_create`, `temp_mail_inbox`, `temp_mail_read`, `dark_joke`, `lyrics` |
70
+ | `dark` | `fake_identity`, `temp_mail_create`, `temp_mail_inbox`, `temp_mail_read`, `dark_joke` |
62
71
 
63
72
  ## License
64
73
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "PandaAPI"
7
- version = "1.0.7"
7
+ version = "1.0.9"
8
8
  authors = [
9
9
  { name = "PANDA" }
10
10
  ]
@@ -1 +0,0 @@
1
- aW1wb3J0IHJlcXVlc3RzCgoKZGVmIHl0X3NlYXJjaChxdWVyeTogc3RyKSAtPiBsaXN0OgogICAgdHJ5OgogICAgICAgIGltcG9ydCB5dF9kbHAKICAgICAgICB5ZGxfb3B0cyA9IHsKICAgICAgICAgICAgInF1aWV0IjogVHJ1ZSwKICAgICAgICAgICAgInNraXBfZG93bmxvYWQiOiBUcnVlLAogICAgICAgICAgICAiZXh0cmFjdF9mbGF0IjogVHJ1ZSwKICAgICAgICB9CiAgICAgICAgd2l0aCB5dF9kbHAuWW91dHViZURMKHlkbF9vcHRzKSBhcyB5ZGw6CiAgICAgICAgICAgIGluZm8gPSB5ZGwuZXh0cmFjdF9pbmZvKGYieXRzZWFyY2g1OntxdWVyeX0iLCBkb3dubG9hZD1GYWxzZSkKICAgICAgICAgICAgZW50cmllcyA9IGluZm8uZ2V0KCJlbnRyaWVzIiwgW10pCiAgICAgICAgICAgIHJldHVybiBbCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgInRpdGxlIjogZS5nZXQoInRpdGxlIiksCiAgICAgICAgICAgICAgICAgICAgInVybCI6IGYiaHR0cHM6Ly95b3V0dWJlLmNvbS93YXRjaD92PXtlLmdldCgnaWQnKX0iLAogICAgICAgICAgICAgICAgICAgICJkdXJhdGlvbiI6IGUuZ2V0KCJkdXJhdGlvbiIpLAogICAgICAgICAgICAgICAgICAgICJjaGFubmVsIjogZS5nZXQoImNoYW5uZWwiKSwKICAgICAgICAgICAgICAgICAgICAiaWQiOiBlLmdldCgiaWQiKSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZvciBlIGluIGVudHJpZXMKICAgICAgICAgICAgXQogICAgZXhjZXB0IEltcG9ydEVycm9yOgogICAgICAgIHJldHVybiBbeyJlcnJvciI6ICJ5dF9kbHAgbm90IGluc3RhbGxlZCIsICJzdWNjZXNzIjogRmFsc2V9XQoKCmRlZiB5dF90aHVtYih2aWRlb19pZDogc3RyKSAtPiBzdHI6CiAgICByZXR1cm4gZiJodHRwczovL2ltZy55b3V0dWJlLmNvbS92aS97dmlkZW9faWR9L21heHJlc2RlZmF1bHQuanBnIgoKCmRlZiBseXJpY3MoYXJ0aXN0OiBzdHIsIHRpdGxlOiBzdHIpIC0+IGRpY3Q6CiAgICAjIC0tLSBQcmltYXJ5OiBseXJpY3Mub3ZoIC0tLQogICAgdHJ5OgogICAgICAgIHVybCA9IGYiaHR0cHM6Ly9hcGkubHlyaWNzLm92aC92MS97YXJ0aXN0fS97dGl0bGV9IgogICAgICAgIHIgPSByZXF1ZXN0cy5nZXQodXJsLCB0aW1lb3V0PTgpCiAgICAgICAgaWYgci5zdGF0dXNfY29kZSA9PSAyMDA6CiAgICAgICAgICAgIGRhdGEgPSByLmpzb24oKQogICAgICAgICAgICBpZiBkYXRhLmdldCgibHlyaWNzIik6CiAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICJzdWNjZXNzIjogVHJ1ZSwKICAgICAgICAgICAgICAgICAgICAiYXJ0aXN0IjogYXJ0aXN0LAogICAgICAgICAgICAgICAgICAgICJ0aXRsZSI6IHRpdGxlLAogICAgICAgICAgICAgICAgICAgICJseXJpY3MiOiBkYXRhWyJseXJpY3MiXSwKICAgICAgICAgICAgICAgICAgICAic3luY2VkIjogRmFsc2UsCiAgICAgICAgICAgICAgICAgICAgInNvdXJjZSI6ICJseXJpY3Mub3ZoIiwKICAgICAgICAgICAgICAgIH0KICAgIGV4Y2VwdCBFeGNlcHRpb246CiAgICAgICAgcGFzcwoKICAgICMgLS0tIEZhbGxiYWNrOiBscmNsaWIubmV0IC0tLQogICAgdHJ5OgogICAgICAgIHVybCA9ICJodHRwczovL2xyY2xpYi5uZXQvYXBpL2dldCIKICAgICAgICBwYXJhbXMgPSB7ImFydGlzdF9uYW1lIjogYXJ0aXN0LCAidHJhY2tfbmFtZSI6IHRpdGxlfQogICAgICAgIHIgPSByZXF1ZXN0cy5nZXQodXJsLCBwYXJhbXM9cGFyYW1zLCB0aW1lb3V0PTgpCiAgICAgICAgaWYgci5zdGF0dXNfY29kZSA9PSAyMDA6CiAgICAgICAgICAgIGRhdGEgPSByLmpzb24oKQogICAgICAgICAgICBzeW5jZWQgPSBkYXRhLmdldCgic3luY2VkTHlyaWNzIikKICAgICAgICAgICAgcGxhaW4gPSBkYXRhLmdldCgicGxhaW5MeXJpY3MiKQogICAgICAgICAgICBpZiBzeW5jZWQgb3IgcGxhaW46CiAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICJzdWNjZXNzIjogVHJ1ZSwKICAgICAgICAgICAgICAgICAgICAiYXJ0aXN0IjogYXJ0aXN0LAogICAgICAgICAgICAgICAgICAgICJ0aXRsZSI6IHRpdGxlLAogICAgICAgICAgICAgICAgICAgICJseXJpY3MiOiBzeW5jZWQgb3IgcGxhaW4sCiAgICAgICAgICAgICAgICAgICAgInN5bmNlZCI6IGJvb2woc3luY2VkKSwKICAgICAgICAgICAgICAgICAgICAic291cmNlIjogImxyY2xpYi5uZXQiLAogICAgICAgICAgICAgICAgfQogICAgZXhjZXB0IEV4Y2VwdGlvbjoKICAgICAgICBwYXNzCgogICAgcmV0dXJuIHsic3VjY2VzcyI6IEZhbHNlLCAiZXJyb3IiOiAiTHlyaWNzIG5vdCBmb3VuZCBvbiBhbnkgc291cmNlIn0K
File without changes
File without changes
File without changes