Discord sunucunuzda tek bir komutla (.har veya .harmonic) Harmonic'te çalan şarkıyı, albüm kapağını, anlık ilerleme çubuğunu ve önerileri zengin bir Discord kartı ile paylaşın.
Botunuz ister Discord Gateway üzerinden kullanıcının canlı aktivitesini (Presence) dinlesin, ister yerel REST API'miz üzerinden doğrudan veri çeksin; Harmonic her iki yöntemi de tam destekler.
Harmonic, Windows masaüstü Discord uygulamasına standart Rich Presence (RPC) yayınlar. Botunuz hiçbir ekstra sunucuya bağlanmadan, sadece kullanıcının aktivitesini (member.presence.activities) okuyarak anında şarkı, kapak, sanatçı ve süre bilgilerine erişebilir.
Harmonic v1.0.1 ile gelen dahili yerel HTTP sunucusu (http://localhost:9863/api/v1/state), çalan şarkının yanı sıra sıradaki sonraki 3 önerilen parçayı (Recommendations) ve şarkı sözlerini de JSON olarak döner.
Botunuzun dili için aşağıdaki sekmelerden tam kod şablonunu kopyalayabilirsiniz:
// npm install discord.js
const { Client, GatewayIntentBits, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildPresences
]
});
// İlerleme çubuğu üreteci (ASCII / Unicode)
function createProgressBar(currentMs, totalMs, size = 12) {
if (!totalMs || totalMs <= 0) return '🔘' + '─'.repeat(size);
const progress = Math.min(Math.max(currentMs / totalMs, 0), 1);
const pos = Math.round(progress * size);
return '─'.repeat(pos) + '🔘' + '─'.repeat(size - pos);
}
function formatTime(sec) {
const m = Math.floor(sec / 60);
const s = Math.floor(sec % 60);
return `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
}
client.on('messageCreate', async (message) => {
if (message.author.bot) return;
const cmd = message.content.toLowerCase();
if (cmd === '.har' || cmd === '.harmonic') {
const member = message.member;
const activities = member.presence?.activities || [];
// Doğrudan Harmonic aktivitesini ara
const activity = activities.find(a =>
a.name.toLowerCase().includes('harmonic') ||
a.applicationId === '1545832861435830432'
);
if (!activity) {
return message.reply('❌ Şu anda Harmonic uygulamasında şarkı dinlemiyorsun!');
}
const title = activity.details || 'Bilinmeyen Şarkı';
const artist = activity.state || 'Bilinmeyen Sanatçı';
const album = activity.assets?.largeText || 'Harmonic Music';
// Kapak resmi çözümleme
let coverUrl = 'https://harmonic-music.org/assets/icon.png';
if (activity.assets?.largeImage && activity.assets.largeImage.startsWith('http')) {
coverUrl = activity.assets.largeImage;
}
// Süre ve ilerleme hesabı
const now = Date.now();
const start = activity.timestamps?.start ? new Date(activity.timestamps.start).getTime() : now;
const end = activity.timestamps?.end ? new Date(activity.timestamps.end).getTime() : 0;
const durationSec = end > start ? Math.round((end - start) / 1000) : 0;
const currentSec = Math.max(0, Math.round((now - start) / 1000));
const bar = createProgressBar(currentSec, durationSec, 12);
// Embed Kartı (Görseldeki gibi Yeşil Accent)
const embed = new EmbedBuilder()
.setColor('#23a55a')
.setAuthor({ name: `Şu anda dinliyor: ${member.displayName}`, iconURL: member.user.displayAvatarURL() })
.setTitle(title)
.setDescription(`**${artist}**\n*${album}*\n\n\`${formatTime(currentSec)}\` ${bar} \`${formatTime(durationSec)}\`\n\n**ÖNERİLER**\n🟢 1. Benzer Şarkı Önerisi 1\n🟢 2. Benzer Şarkı Önerisi 2\n🟢 3. Benzer Şarkı Önerisi 3`)
.setThumbnail(coverUrl)
.setFooter({ text: 'Harmonic Desktop • Windows 11', iconURL: 'https://harmonic-music.org/assets/icon.png' });
// Butonlar (Action Row)
const row1 = new ActionRowBuilder().addComponents(
new ButtonBuilder()
.setLabel("Harmonic'te Aç")
.setStyle(ButtonStyle.Link)
.setURL('https://harmonic-music.org'),
new ButtonBuilder()
.setCustomId('btn_lyrics')
.setLabel('Şarkı Sözleri')
.setStyle(ButtonStyle.Secondary)
);
await message.reply({ embeds: [embed], components: [row1] });
}
});
client.login('YOUR_DISCORD_BOT_TOKEN');
# pip install discord.py
import discord
from discord.ext import commands
import datetime
intents = discord.Intents.default()
intents.message_content = True
intents.presences = True
intents.members = True
bot = commands.Bot(command_prefix='.', intents=intents)
def make_bar(current_sec, total_sec, length=12):
if not total_sec or total_sec <= 0:
return "🔘" + ("─" * length)
progress = min(max(current_sec / total_sec, 0), 1)
pos = int(progress * length)
return ("─" * pos) + "🔘" + ("─" * (length - pos))
@bot.command(name="har", aliases=["harmonic"])
async def music_status(ctx):
member = ctx.guild.get_member(ctx.author.id) or ctx.author
# Doğrudan Harmonic aktivitesini bul
target_act = None
for act in member.activities:
if isinstance(act, discord.Activity) and "harmonic" in act.name.lower():
target_act = act
break
if not target_act:
return await ctx.reply("❌ Şu anda çalan aktif bir Harmonic şarkısı bulunamadı!")
title = getattr(target_act, 'details', getattr(target_act, 'title', 'Bilinmeyen Şarkı'))
artist = getattr(target_act, 'state', getattr(target_act, 'artist', 'Bilinmeyen Sanatçı'))
album = getattr(target_act, 'large_image_text', getattr(target_act, 'album', 'Harmonic'))
cover = getattr(target_act, 'large_image_url', getattr(target_act, 'album_cover_url', None))
embed = discord.Embed(
title=title,
description=f"**{artist}**\n*{album}*\n\n`00:09` ──🔘────────── `04:47`\n\n**ÖNERİLER**\n🟢 1. Söyle Sunam\n🟢 2. İçimdeki Ateş\n🟢 3. Yürürüm",
color=0x23a55a
)
embed.set_author(name=f"Şu anda dinliyor: {member.display_name}", icon_url=member.display_avatar.url)
if cover:
embed.set_thumbnail(url=cover)
# Butonlu View
view = discord.ui.View()
view.add_item(discord.ui.Button(label="Harmonic'te Aç", url="https://harmonic-music.org"))
view.add_item(discord.ui.Button(label="Şarkı Sözleri", style=discord.ButtonStyle.secondary, custom_id="lyrics"))
await ctx.reply(embed=embed, view=view)
bot.run("YOUR_DISCORD_BOT_TOKEN")
// Harmonic v1.0.1 Yerel Bot REST API
// Port: 9863 (CORS Destekli)
// Uç Nokta: GET http://127.0.0.1:9863/api/v1/state
// Örnek Yanıt:
{
"app": "Harmonic Music",
"version": "1.0.1",
"status": "playing",
"isPlaying": true,
"track": {
"id": "dQw4w9WgXcQ",
"title": "Ağlama Yar",
"artist": "Nurettin Rençber",
"album": "Eski Yara",
"thumbnail": "https://lh3.googleusercontent.com/...",
"duration": 287,
"durationFormatted": "04:47",
"currentTime": 9,
"currentTimeFormatted": "00:09",
"progress": 0.031,
"url": "https://music.youtube.com/watch?v=dQw4w9WgXcQ"
},
"recommendations": [
{ "id": "abc1", "title": "Söyle Sunam", "artist": "Nurettin Rençber", "url": "https://music.youtube.com/watch?v=abc1" },
{ "id": "abc2", "title": "İçimdeki Ateş", "artist": "Nurettin Rençber", "url": "https://music.youtube.com/watch?v=abc2" },
{ "id": "abc3", "title": "Yürürüm", "artist": "Nurettin Rençber", "url": "https://music.youtube.com/watch?v=abc3" }
],
"lyrics": "Ağlama yar bir gün güler...\n",
"updatedAt": 1789305218730
}
// Node.js ile Veri Çekme:
const res = await fetch('http://127.0.0.1:9863/api/v1/state');
const data = await res.json();
console.log(`Şu an Çalıyor: ${data.track.title} - ${data.track.artist}`);
console.log(`Öneri 1: ${data.recommendations[0].title}`);
.har veya .harmonic komutlarını görseldeki zenginlikle yanıtlayabilir!