Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20a36703e6 | ||
|
|
f9f0ba9b1f | ||
|
|
d60cd75786 | ||
|
|
cbf39d2bae | ||
|
|
bb2b31bb61 | ||
|
|
cdbf448291 |
@@ -6,41 +6,39 @@ on:
|
|||||||
- '*' # Trigger on any git tag
|
- '*' # Trigger on any git tag
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
build-image:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: docker:rc-dind
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Install dedps
|
||||||
|
run: |
|
||||||
|
apk add --no-cache nodejs npm git
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up Podman
|
- name: Build container image
|
||||||
|
env:
|
||||||
|
IMAGE_NAME: papryk/dj-spangebob
|
||||||
|
TAG: ${{ github.ref_name }}
|
||||||
run: |
|
run: |
|
||||||
export XDG_RUNTIME_DIR=/tmp/run-user
|
docker build -t "$IMAGE_NAME:$TAG" .
|
||||||
export HOME=/tmp/home
|
|
||||||
mkdir -p $XDG_RUNTIME_DIR $HOME
|
|
||||||
# Ensure Podman is installed
|
|
||||||
if ! command -v podman &> /dev/null; then
|
|
||||||
echo "Podman not found, installing..."
|
|
||||||
sudo apt-get update && sudo apt-get install -y podman
|
|
||||||
fi
|
|
||||||
podman info || true # info will fail if storage driver is overlay, ignore
|
|
||||||
|
|
||||||
|
|
||||||
- name: Log in to Docker registry
|
- name: Log in to Docker registry
|
||||||
run: |
|
|
||||||
echo "${REGISTRY_PASSWORD}" | podman login ${GITEA_REGISTRY} \
|
|
||||||
--username ${REGISTRY_USERNAME} --password-stdin
|
|
||||||
env:
|
env:
|
||||||
|
REGISTRY: https://gitea.papryk.com
|
||||||
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||||||
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
echo "$REGISTRY_PASSWORD" | docker "$REGISTRY" -u "$REGISTRY_USERNAME" --password-stdin
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
run: |
|
|
||||||
IMAGE_TAG="Papryk/dj-spangebob:${{ gitea.ref_name }}"
|
|
||||||
echo "Building image $IMAGE_TAG"
|
|
||||||
podman build -t "$IMAGE_TAG" .
|
|
||||||
echo "Pushing image $IMAGE_TAG"
|
|
||||||
podman push "$IMAGE_TAG"
|
|
||||||
env:
|
env:
|
||||||
TAG: ${{ gitea.ref_name }}
|
REGISTRY: https://gitea.papryk.com
|
||||||
|
IMAGE_NAME: Papryk/dj-spangebob
|
||||||
|
TAG: ${{ github.ref_name }}
|
||||||
|
run: |
|
||||||
|
docker push "$REGISTRY/$IMAGE_NAME:$TAG"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
FROM node:20-alpine
|
FROM node:22-alpine
|
||||||
|
|
||||||
RUN apk add --no-cache ffmpeg yt-dlp
|
RUN apk add --no-cache wget ffmpeg #yt-dlp
|
||||||
|
RUN wget -P /tmp https://github.com/yt-dlp/yt-dlp/releases/download/2026.01.31/yt-dlp_musllinux
|
||||||
|
RUN mv /tmp/yt-dlp_musllinux /usr/bin/yt-dlp
|
||||||
|
RUN chmod 777 /usr/bin/yt-dlp
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
36
history/29-01-2026.json
Normal file
36
history/29-01-2026.json
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"interaction": {
|
||||||
|
"type": 2,
|
||||||
|
"id": "1466473802148872486",
|
||||||
|
"applicationId": "887789346277691402",
|
||||||
|
"channelId": "470712099753164811",
|
||||||
|
"guildId": "343827205878710273",
|
||||||
|
"user": "264739894641950720",
|
||||||
|
"member": "264739894641950720",
|
||||||
|
"version": 1,
|
||||||
|
"appPermissions": "2230881414020816",
|
||||||
|
"memberPermissions": "2230883322429171",
|
||||||
|
"locale": "pl",
|
||||||
|
"guildLocale": "en-US",
|
||||||
|
"entitlements": [],
|
||||||
|
"authorizingIntegrationOwners": {
|
||||||
|
"0": "343827205878710273"
|
||||||
|
},
|
||||||
|
"context": 0,
|
||||||
|
"attachmentSizeLimit": 10485760,
|
||||||
|
"commandId": "1452614990078021710",
|
||||||
|
"commandName": "play",
|
||||||
|
"commandType": 1,
|
||||||
|
"commandGuildId": null,
|
||||||
|
"deferred": true,
|
||||||
|
"replied": true,
|
||||||
|
"ephemeral": false,
|
||||||
|
"webhook": {
|
||||||
|
"id": "887789346277691402"
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"url": "https://soundcloud.com/musicbymoonlght/4th-of-july-rock-x-house-mix-by-moonlght-vol-2?si=93777764ee5c404db6f3fb3c6dc347d8&utm_source=clipboard&utm_medium=text&utm_campaign=social_sharing"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -7,6 +7,7 @@ import queue from "./queue"
|
|||||||
import resume from "./resume"
|
import resume from "./resume"
|
||||||
import skip from "./skip"
|
import skip from "./skip"
|
||||||
import stop from "./stop"
|
import stop from "./stop"
|
||||||
|
import loop from "./loop"
|
||||||
|
|
||||||
export const commands: { [key: string]: Command } = {
|
export const commands: { [key: string]: Command } = {
|
||||||
ping,
|
ping,
|
||||||
@@ -18,5 +19,6 @@ export const commands: { [key: string]: Command } = {
|
|||||||
stop,
|
stop,
|
||||||
pause,
|
pause,
|
||||||
skip,
|
skip,
|
||||||
|
loop,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
src/commands/loop.ts
Normal file
34
src/commands/loop.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { CacheType, ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js';
|
||||||
|
import { toggleLoop } from '../playback';
|
||||||
|
import { formatFilePath } from '../util/downloader'
|
||||||
|
|
||||||
|
|
||||||
|
const name = "loop"
|
||||||
|
|
||||||
|
function register() {
|
||||||
|
return new SlashCommandBuilder()
|
||||||
|
.setName(name)
|
||||||
|
.setDescription('loop current song')
|
||||||
|
}
|
||||||
|
|
||||||
|
async function execute(interaction: ChatInputCommandInteraction<CacheType>) {
|
||||||
|
try {
|
||||||
|
await interaction.deferReply()
|
||||||
|
const audio = toggleLoop()
|
||||||
|
if (audio) {
|
||||||
|
await interaction.editReply(`looped ${formatFilePath(audio.url)}`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await interaction.editReply(`Loop turned off`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
await interaction.reply('Coś poszło nie tak :/');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name,
|
||||||
|
register,
|
||||||
|
execute
|
||||||
|
}
|
||||||
10
src/global.d.ts
vendored
10
src/global.d.ts
vendored
@@ -10,7 +10,13 @@ type AudioFile = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Queue = {
|
type Queue = {
|
||||||
songList: AudioFile[],
|
songList: AudioFile[]
|
||||||
current: AudioFile | null,
|
current: AudioFile | null
|
||||||
|
loop: AudioFile | null
|
||||||
|
}
|
||||||
|
|
||||||
|
type HistoryObject = {
|
||||||
|
interaction: ChatInputCommandInteraction<CacheType>
|
||||||
|
url: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { updatePlayer } from './playback';
|
|||||||
import SpotifyWebApi from 'spotify-web-api-node';
|
import SpotifyWebApi from 'spotify-web-api-node';
|
||||||
|
|
||||||
export const DATA_DIR = "./data";
|
export const DATA_DIR = "./data";
|
||||||
|
export const HISTORY_DIR_PATH = process.env.HISTORY_DIR_PATH ?? "./history";
|
||||||
|
|
||||||
// AUDIO
|
// AUDIO
|
||||||
export const player = createAudioPlayer();
|
export const player = createAudioPlayer();
|
||||||
|
|||||||
@@ -3,20 +3,30 @@ import { player } from "./main";
|
|||||||
import { CacheType, ChatInputCommandInteraction } from "discord.js";
|
import { CacheType, ChatInputCommandInteraction } from "discord.js";
|
||||||
import { getAudioFile } from "./util/downloader";
|
import { getAudioFile } from "./util/downloader";
|
||||||
import { playSong } from "./util/helpers";
|
import { playSong } from "./util/helpers";
|
||||||
|
import { add_to_history } from "./util/history";
|
||||||
|
|
||||||
const queue: Queue = {
|
const queue: Queue = {
|
||||||
songList: [],
|
songList: [],
|
||||||
current: null
|
current: null,
|
||||||
|
loop: null,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toggleLoop(): AudioFile | null {
|
||||||
|
if (queue.loop) queue.loop = null
|
||||||
|
else queue.loop = queue.current
|
||||||
|
return queue.loop
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function requestSong(
|
export async function requestSong(
|
||||||
interaction: ChatInputCommandInteraction<CacheType>,
|
interaction: ChatInputCommandInteraction<CacheType>,
|
||||||
url: string) {
|
url: string,
|
||||||
|
user?: any
|
||||||
|
) {
|
||||||
|
|
||||||
const path = await getAudioFile(url)
|
const path = await getAudioFile(url)
|
||||||
queue.songList.push({ path, url })
|
queue.songList.push({ path, url })
|
||||||
|
add_to_history({ interaction, url })
|
||||||
updatePlayer()
|
updatePlayer()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function forceRequestSong(
|
export async function forceRequestSong(
|
||||||
@@ -33,7 +43,7 @@ export async function forceRequestSong(
|
|||||||
|
|
||||||
export async function updatePlayer() {
|
export async function updatePlayer() {
|
||||||
if (player.state.status === AudioPlayerStatus.Idle) {
|
if (player.state.status === AudioPlayerStatus.Idle) {
|
||||||
const nextSong = queue.songList.shift()
|
const nextSong = queue.loop ?? queue.songList.shift()
|
||||||
if (!nextSong) {
|
if (!nextSong) {
|
||||||
queue.current = null
|
queue.current = null
|
||||||
return
|
return
|
||||||
|
|||||||
33
src/util/history.ts
Normal file
33
src/util/history.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import path from "node:path";
|
||||||
|
import fs from "node:fs";
|
||||||
|
import { HISTORY_DIR_PATH } from "../main";
|
||||||
|
|
||||||
|
export async function add_to_history(history: HistoryObject) {
|
||||||
|
const today = new Date();
|
||||||
|
|
||||||
|
const day = String(today.getDate()).padStart(2, '0');
|
||||||
|
const month = String(today.getMonth() + 1).padStart(2, '0');
|
||||||
|
const year = today.getFullYear();
|
||||||
|
|
||||||
|
const file_name = `${day}-${month}-${year}.json`;
|
||||||
|
const file_path = path.join(HISTORY_DIR_PATH, file_name)
|
||||||
|
|
||||||
|
if (!fs.existsSync(HISTORY_DIR_PATH)) {
|
||||||
|
fs.mkdirSync(HISTORY_DIR_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const content = fs.readFileSync(file_path, 'utf8');
|
||||||
|
data = JSON.parse(content);
|
||||||
|
} catch (err) {
|
||||||
|
data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
data.push(history)
|
||||||
|
|
||||||
|
fs.writeFileSync(file_path, JSON.stringify(data, (key, value) => {
|
||||||
|
return typeof value === "bigint" ? value.toString() : value
|
||||||
|
}, 2));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user