initial commit
This commit is contained in:
commit
c094b5770c
113 changed files with 6879 additions and 0 deletions
16
pkgs/default.nix
Normal file
16
pkgs/default.nix
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
pkgs ? import <nixpkgs>,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
gitingest = pkgs.python3Packages.callPackage ./gitingest { };
|
||||
open-webui-desktop = pkgs.callPackage ./open-webui-desktop { };
|
||||
otp = pkgs.callPackage ./otp { };
|
||||
pdf2printable = pkgs.callPackage ./pdf2printable { };
|
||||
transcribe = pkgs.callPackage ./transcribe { };
|
||||
udiskie-dmenu = pkgs.callPackage ./udiskie-dmenu { };
|
||||
yt2rss = pkgs.callPackage ./yt2rss { };
|
||||
|
||||
# spotify-to-tidal = pkgs.callPackage ./spotify-to-tidal { }; # FIXME
|
||||
}
|
||||
100
pkgs/gitingest/default.nix
Normal file
100
pkgs/gitingest/default.nix
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
lib,
|
||||
buildPythonPackage,
|
||||
fetchFromGitHub,
|
||||
|
||||
# Dependencies
|
||||
setuptools,
|
||||
click,
|
||||
fastapi,
|
||||
pathspec,
|
||||
pydantic,
|
||||
python-dotenv,
|
||||
slowapi,
|
||||
starlette,
|
||||
tiktoken,
|
||||
tomli,
|
||||
uvicorn,
|
||||
loguru,
|
||||
|
||||
# Tests
|
||||
httpx,
|
||||
jinja2,
|
||||
gitMinimal,
|
||||
pytest-asyncio,
|
||||
pytest-mock,
|
||||
pytestCheckHook,
|
||||
python-multipart,
|
||||
}:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "gitingest";
|
||||
version = "0.3.1";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "cyclotruc";
|
||||
repo = "gitingest";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-drsncGneZyOCC2GJbrDM+bf4QGI2luacxMhrmdk03l4=";
|
||||
};
|
||||
|
||||
build-system = [
|
||||
setuptools
|
||||
];
|
||||
|
||||
dependencies = [
|
||||
click
|
||||
fastapi
|
||||
pathspec
|
||||
pydantic
|
||||
python-dotenv
|
||||
slowapi
|
||||
starlette
|
||||
tiktoken
|
||||
tomli
|
||||
uvicorn
|
||||
|
||||
httpx
|
||||
loguru
|
||||
];
|
||||
|
||||
pythonImportsCheck = [
|
||||
"gitingest"
|
||||
];
|
||||
|
||||
nativeCheckInputs = [
|
||||
httpx
|
||||
jinja2
|
||||
gitMinimal
|
||||
pytest-asyncio
|
||||
pytest-mock
|
||||
pytestCheckHook
|
||||
python-multipart
|
||||
];
|
||||
|
||||
doCheck = false;
|
||||
|
||||
disabledTests = [
|
||||
# Tests require network
|
||||
"test_cli_with_default_options"
|
||||
"test_cli_with_options"
|
||||
"test_cli_with_stdout_output"
|
||||
"test_cli_writes_file"
|
||||
"test_clone_specific_branch"
|
||||
"test_include_ignore_patterns"
|
||||
"test_ingest_with_gitignore"
|
||||
"test_parse_query_with_branch"
|
||||
"test_parse_query_without_host"
|
||||
"test_run_ingest_query"
|
||||
];
|
||||
|
||||
meta = {
|
||||
changelog = "https://github.com/cyclotruc/gitingest/releases/tag/${src.tag}";
|
||||
description = "Replace 'hub' with 'ingest' in any github url to get a prompt-friendly extract of a codebase";
|
||||
homepage = "https://github.com/cyclotruc/gitingest";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [ ];
|
||||
mainProgram = "gitingest";
|
||||
};
|
||||
}
|
||||
68
pkgs/gitingest/default_nix-init.nix
Normal file
68
pkgs/gitingest/default_nix-init.nix
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
{
|
||||
lib,
|
||||
python3,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "gitingest";
|
||||
version = "0.3.1";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "coderamp-labs";
|
||||
repo = "gitingest";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-drsncGneZyOCC2GJbrDM+bf4QGI2luacxMhrmdk03l4=";
|
||||
};
|
||||
|
||||
build-system = [
|
||||
python3.pkgs.setuptools
|
||||
python3.pkgs.wheel
|
||||
];
|
||||
|
||||
dependencies = with python3.pkgs; [
|
||||
click
|
||||
httpx
|
||||
loguru
|
||||
pathspec
|
||||
pydantic
|
||||
python-dotenv
|
||||
starlette
|
||||
strenum
|
||||
tiktoken
|
||||
typing-extensions
|
||||
];
|
||||
|
||||
optional-dependencies = with python3.pkgs; {
|
||||
dev = [
|
||||
eval-type-backport
|
||||
pre-commit
|
||||
pytest
|
||||
pytest-asyncio
|
||||
pytest-cov
|
||||
pytest-mock
|
||||
];
|
||||
server = [
|
||||
boto3
|
||||
fastapi
|
||||
prometheus-client
|
||||
sentry-sdk
|
||||
slowapi
|
||||
uvicorn
|
||||
];
|
||||
};
|
||||
|
||||
pythonImportsCheck = [
|
||||
"gitingest"
|
||||
];
|
||||
|
||||
meta = {
|
||||
description = "Replace 'hub' with 'ingest' in any GitHub URL to get a prompt-friendly extract of a codebase";
|
||||
homepage = "https://github.com/coderamp-labs/gitingest";
|
||||
changelog = "https://github.com/coderamp-labs/gitingest/blob/${src.rev}/CHANGELOG.md";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [ ];
|
||||
mainProgram = "gitingest";
|
||||
};
|
||||
}
|
||||
60
pkgs/open-webui-desktop/default.nix
Normal file
60
pkgs/open-webui-desktop/default.nix
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
lib,
|
||||
buildNpmPackage,
|
||||
fetchFromGitHub,
|
||||
electron,
|
||||
}:
|
||||
|
||||
buildNpmPackage rec {
|
||||
pname = "open-webui-desktop";
|
||||
version = "7e54042";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "open-webui";
|
||||
repo = "desktop";
|
||||
rev = "build-e${version}";
|
||||
hash = "sha256-eW3B8CS2T46Z91JRAlZJ3rNxAru4p7eJwyxn6P20pnA=";
|
||||
};
|
||||
|
||||
npmDepsHash = "sha256-HdkgbcLzY/9T26hpw6Jej8sUWlcIIn1FkJ7IVvG3P4o=";
|
||||
|
||||
makeCacheWritable = true;
|
||||
|
||||
# Create .npmrc to prevent scripts from running during install
|
||||
postPatch = ''
|
||||
cat >> .npmrc << 'EOF'
|
||||
ignore-scripts=true
|
||||
EOF
|
||||
'';
|
||||
|
||||
preInstall = ''
|
||||
sed -i '/postinstall/d' package.json
|
||||
'';
|
||||
|
||||
npmRebuild = false;
|
||||
|
||||
buildPhase = ''
|
||||
export ELECTRON_SKIP_BINARY_DOWNLOAD=1
|
||||
npm run build
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/opt/${pname}
|
||||
cp -r out $out/opt/${pname}/
|
||||
cp -r resources $out/opt/${pname}/
|
||||
cp -r node_modules $out/opt/${pname}/
|
||||
mkdir -p $out/bin
|
||||
|
||||
makeWrapper ${electron}/bin/electron $out/bin/${pname} \
|
||||
--add-flags "$out/opt/${pname}/out/main/index.js" \
|
||||
--run "cd $out/opt/${pname}"
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Open WebUI Desktop 🌐 (Alpha)";
|
||||
homepage = "https://github.com/open-webui/desktop";
|
||||
# license = lib.licenses.TODO;
|
||||
mainProgram = "open-webui-desktop";
|
||||
platforms = lib.platforms.linux;
|
||||
};
|
||||
}
|
||||
15
pkgs/otp/default.nix
Normal file
15
pkgs/otp/default.nix
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
writeShellScriptBin,
|
||||
symlinkJoin,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
wrapped = writeShellScriptBin "otp" (builtins.readFile ./otp.sh);
|
||||
in
|
||||
symlinkJoin {
|
||||
name = "otp";
|
||||
paths = [
|
||||
wrapped
|
||||
];
|
||||
}
|
||||
25
pkgs/otp/otp.sh
Normal file
25
pkgs/otp/otp.sh
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
DMENU="bemenu"
|
||||
OPTIONS="github\nth-koeln"
|
||||
|
||||
CHOICE=$(echo -e "$OPTIONS" | "$DMENU" -p "OTP:")
|
||||
|
||||
get_pass() {
|
||||
pass otp -c "$1" 2>/dev/null
|
||||
}
|
||||
|
||||
case "$CHOICE" in
|
||||
"github")
|
||||
get_pass "www/github.com"
|
||||
;;
|
||||
"th-koeln")
|
||||
get_pass "www/login.th-koeln.de"
|
||||
;;
|
||||
*)
|
||||
echo "Error: Unknown option '$CHOICE'"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
39
pkgs/pdf2printable/default.nix
Normal file
39
pkgs/pdf2printable/default.nix
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
writeShellScriptBin,
|
||||
pdftk,
|
||||
texlivePackages,
|
||||
}:
|
||||
|
||||
let
|
||||
_pdfjam = "${texlivePackages.pdfjam}/bin/pdfjam";
|
||||
_pdftk = "${pdftk}/bin/pdftk";
|
||||
in
|
||||
writeShellScriptBin "pdf2printable" ''
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "Usage: $0 input.pdf output.pdf"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
input_pdf="$1"
|
||||
output_pdf="$2"
|
||||
|
||||
even_pdf="even.pdf"
|
||||
even_rotated_pdf="even_rotated.pdf"
|
||||
landscape_pdf="landscape.pdf"
|
||||
odd_pdf="odd.pdf"
|
||||
|
||||
# Convert the PDF to landscape
|
||||
${_pdfjam} --landscape --nup 2x1 "$input_pdf" -o "$landscape_pdf"
|
||||
|
||||
# Split the PDF into odd and even pages
|
||||
${_pdftk} "$landscape_pdf" cat odd output "$odd_pdf"
|
||||
${_pdftk} "$landscape_pdf" cat even output "$even_pdf"
|
||||
|
||||
# Rotate the even pages by 180 degrees
|
||||
${_pdfjam} --landscape "$even_pdf" --angle 180 --outfile "$even_rotated_pdf"
|
||||
|
||||
# Merge the odd and rotated even pages
|
||||
${_pdftk} A="$odd_pdf" B="$even_rotated_pdf" shuffle A B output "$output_pdf"
|
||||
|
||||
rm "$odd_pdf" "$even_pdf" "$landscape_pdf" "$even_rotated_pdf"
|
||||
''
|
||||
44
pkgs/spotify-to-tidal/default.nix
Normal file
44
pkgs/spotify-to-tidal/default.nix
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
lib,
|
||||
python3,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "spotify-to-tidal";
|
||||
version = "1.0.4";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "spotify2tidal";
|
||||
repo = "spotify_to_tidal";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-NexwO4Qwv1P58QAgBHPfCf4Q/mhTicWHaRubh8En9AE=";
|
||||
};
|
||||
|
||||
build-system = [
|
||||
python3.pkgs.setuptools
|
||||
python3.pkgs.wheel
|
||||
];
|
||||
|
||||
dependencies = with python3.pkgs; [
|
||||
pytest
|
||||
pytest-mock
|
||||
pyyaml
|
||||
spotipy
|
||||
sqlalchemy
|
||||
tidalapi
|
||||
tqdm
|
||||
];
|
||||
|
||||
pythonImportsCheck = [
|
||||
"spotify_to_tidal"
|
||||
];
|
||||
|
||||
meta = {
|
||||
description = "A command line tool for importing your Spotify playlists into Tidal";
|
||||
homepage = "https://github.com/spotify2tidal/spotify_to_tidal";
|
||||
license = lib.licenses.agpl3Only;
|
||||
mainProgram = "spotify-to-tidal";
|
||||
};
|
||||
}
|
||||
22
pkgs/transcribe/default.nix
Normal file
22
pkgs/transcribe/default.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
python3Packages,
|
||||
...
|
||||
}:
|
||||
|
||||
python3Packages.buildPythonApplication {
|
||||
pname = "transcribe";
|
||||
version = "1.0.0";
|
||||
|
||||
src = ./.;
|
||||
pyproject = true;
|
||||
|
||||
build-system = [ python3Packages.setuptools ];
|
||||
|
||||
propagatedBuildInputs = [ python3Packages.openai ];
|
||||
|
||||
doCheck = false;
|
||||
|
||||
meta = {
|
||||
description = "Transcribe a given audio file using the OpenAI API.";
|
||||
};
|
||||
}
|
||||
7
pkgs/transcribe/setup.py
Normal file
7
pkgs/transcribe/setup.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name='transcribe',
|
||||
version='1.0.0',
|
||||
scripts=['transcribe'],
|
||||
)
|
||||
47
pkgs/transcribe/transcribe
Normal file
47
pkgs/transcribe/transcribe
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
from openai import OpenAI
|
||||
|
||||
def transcribe_audio(file_path):
|
||||
"""Transcribe the given audio file using OpenAI API."""
|
||||
if not os.environ.get("OPENAI_API_KEY"):
|
||||
print("Error: OPENAI_API_KEY environment variable is not set.")
|
||||
return None
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
print(f"Error: File '{file_path}' not found.")
|
||||
return None
|
||||
|
||||
try:
|
||||
client = OpenAI()
|
||||
|
||||
with open(file_path, "rb") as audio_file:
|
||||
transcription = client.audio.transcriptions.create(
|
||||
# model="gpt-4o-transcribe",
|
||||
model="whisper-1",
|
||||
file=audio_file,
|
||||
response_format="text"
|
||||
)
|
||||
|
||||
return transcription
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error occurred during transcription: {e}")
|
||||
return None
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: transcribe <audio_file_path>")
|
||||
sys.exit(1)
|
||||
|
||||
audio_file_path = sys.argv[1]
|
||||
|
||||
transcription = transcribe_audio(audio_file_path)
|
||||
|
||||
if transcription:
|
||||
print(transcription)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
1241
pkgs/udiskie-dmenu/Cargo.lock
generated
Normal file
1241
pkgs/udiskie-dmenu/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
9
pkgs/udiskie-dmenu/Cargo.toml
Normal file
9
pkgs/udiskie-dmenu/Cargo.toml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "udiskie-dmenu"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
notify-rust = "4.5.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
13
pkgs/udiskie-dmenu/default.nix
Normal file
13
pkgs/udiskie-dmenu/default.nix
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
lib,
|
||||
rustPlatform,
|
||||
...
|
||||
}:
|
||||
|
||||
rustPlatform.buildRustPackage {
|
||||
pname = "udiskie-dmenu";
|
||||
version = "0.1.0";
|
||||
|
||||
cargoLock.lockFile = ./Cargo.lock;
|
||||
src = lib.cleanSource ./.;
|
||||
}
|
||||
190
pkgs/udiskie-dmenu/src/main.rs
Normal file
190
pkgs/udiskie-dmenu/src/main.rs
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
use notify_rust::Notification;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::io::{self, Write};
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct DeviceInfo {
|
||||
label: Option<String>,
|
||||
isLuks: Option<bool>,
|
||||
mountPath: Option<String>,
|
||||
devPath: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match run_udiskie_info() {
|
||||
Ok(block_devices) => {
|
||||
let options = parse_udiskie_info(&block_devices);
|
||||
if options.is_empty() {
|
||||
notify_if_err("Nothing to unmount / mount".to_string());
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
match get_selection(pretty_print(&options)) {
|
||||
Ok(Some(selected)) => {
|
||||
let parsed_selection = parse_selection(&selected, &options);
|
||||
for device in parsed_selection {
|
||||
process_device(&device);
|
||||
}
|
||||
}
|
||||
Ok(None) => {} // User cancelled input, do nothing
|
||||
Err(err) => notify_if_err(err),
|
||||
}
|
||||
}
|
||||
Err(err) => notify_if_err(err),
|
||||
}
|
||||
}
|
||||
|
||||
fn run_udiskie_info() -> Result<Vec<DeviceInfo>, String> {
|
||||
let output = Command::new("udiskie-info")
|
||||
.args(&["-C", "-a", "-o", r#""label":"{ui_label}", "isLuks":"{is_luks}", "mountPath": "{mount_path}""#])
|
||||
.output()
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(format!(
|
||||
"Error running `udiskie-info`: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
));
|
||||
}
|
||||
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
parse_udiskie_json(&stdout)
|
||||
}
|
||||
|
||||
fn parse_udiskie_json(json_lines: &str) -> Result<Vec<DeviceInfo>, String> {
|
||||
json_lines
|
||||
.lines()
|
||||
.filter(|line| !line.is_empty())
|
||||
.map(|line| {
|
||||
let wrapped_line = format!("{{{}}}", line);
|
||||
serde_json::from_str(&wrapped_line).map_err(|e| format!("JSON parsing error: {}", e))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn parse_udiskie_info(devices: &[DeviceInfo]) -> HashMap<String, DeviceInfo> {
|
||||
let mut options: HashMap<String, DeviceInfo> = HashMap::new();
|
||||
for device in devices {
|
||||
if device.devPath.starts_with("/dev/loop") {
|
||||
// Skip snap packages
|
||||
continue;
|
||||
}
|
||||
|
||||
let key = device.devPath.clone();
|
||||
if let Some(existing) = options.get(&key) {
|
||||
if existing.mountPath.is_some() && device.mountPath.is_none() {
|
||||
continue;
|
||||
}
|
||||
if existing.isLuks.unwrap_or(false) && !device.isLuks.unwrap_or(false) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
options.insert(key, device.clone());
|
||||
}
|
||||
options
|
||||
}
|
||||
|
||||
fn pretty_print(parsed_info: &HashMap<String, DeviceInfo>) -> String {
|
||||
let mut output = String::new();
|
||||
for (dev_path, device) in parsed_info {
|
||||
let dev_path_padded = format!("{: <9}", dev_path);
|
||||
let label_or_mount_path = device
|
||||
.mountPath
|
||||
.clone()
|
||||
.or_else(|| device.label.clone())
|
||||
.unwrap_or_else(|| "<unknown>".to_string());
|
||||
output.push_str(&format!("{}: {}\n", dev_path_padded, label_or_mount_path));
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
fn get_selection(options: String) -> Result<Option<String>, String> {
|
||||
let launcher = std::env::var("UDISKIE_DMENU_LAUNCHER").unwrap_or_else(|_| "dmenu".to_string());
|
||||
|
||||
let mut child = Command::new(launcher)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
if let Some(stdin) = child.stdin.as_mut() {
|
||||
stdin
|
||||
.write_all(options.as_bytes())
|
||||
.map_err(|e| e.to_string())?;
|
||||
}
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
match output.status.code() {
|
||||
Some(0) | Some(10) => {
|
||||
let selection = String::from_utf8_lossy(&output.stdout).to_string();
|
||||
Ok(Some(selection))
|
||||
}
|
||||
Some(_) | None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_selection(selection: &str, options: &HashMap<String, DeviceInfo>) -> Vec<DeviceInfo> {
|
||||
let mut devices = Vec::new();
|
||||
|
||||
for line in selection.lines() {
|
||||
if let Some((dev_path, _label_or_mount)) = line.split_once(":") {
|
||||
let trimmed_path = dev_path.trim();
|
||||
if let Some(device) = options.get(trimmed_path) {
|
||||
devices.push(device.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
devices
|
||||
}
|
||||
|
||||
fn notify_if_err(err: String) {
|
||||
Notification::new()
|
||||
.summary("Error")
|
||||
.body(&err)
|
||||
.show()
|
||||
.ok();
|
||||
eprintln!("{}", err);
|
||||
}
|
||||
|
||||
fn process_device(device: &DeviceInfo) {
|
||||
let udiskie_opt = if device.isLuks.unwrap_or(false) {
|
||||
"--force"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
if let Some(mount_path) = &device.mountPath {
|
||||
run_command(
|
||||
&format!("udiskie-umount {} \"{}\"", udiskie_opt, mount_path),
|
||||
Some("Failed to unmount device"),
|
||||
);
|
||||
} else if let Some(label) = &device.label {
|
||||
run_command(
|
||||
&format!("udiskie-mount {} \"{}\"", udiskie_opt, device.devPath),
|
||||
Some(&format!("Failed to mount device: {}", label)),
|
||||
);
|
||||
} else {
|
||||
notify_if_err("Unknown device - aborting".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
fn run_command(command: &str, error_msg: Option<&str>) {
|
||||
let status = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(command)
|
||||
.status()
|
||||
.unwrap_or_else(|e| panic!("Failed to execute command: {}", e));
|
||||
|
||||
if !status.success() {
|
||||
if let Some(msg) = error_msg {
|
||||
notify_if_err(msg.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
15
pkgs/yt2rss/default.nix
Normal file
15
pkgs/yt2rss/default.nix
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
writeShellScriptBin,
|
||||
symlinkJoin,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
wrapped = writeShellScriptBin "yt2rss" (builtins.readFile ./yt2rss.sh);
|
||||
in
|
||||
symlinkJoin {
|
||||
name = "create";
|
||||
paths = [
|
||||
wrapped
|
||||
];
|
||||
}
|
||||
21
pkgs/yt2rss/yt2rss.sh
Normal file
21
pkgs/yt2rss/yt2rss.sh
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: $0 <url>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
url=$1
|
||||
|
||||
# Check if input URL is a playlist URL
|
||||
if [[ "$url" == *"playlist"* ]]; then
|
||||
playlist_id=$(echo "$url" | grep -o 'list=[A-Za-z0-9_-]*' | cut -d'=' -f2)
|
||||
|
||||
if [ -n "$playlist_id" ]; then
|
||||
echo "https://www.youtube.com/feeds/videos.xml?playlist_id=$playlist_id"
|
||||
else
|
||||
echo "Could not extract playlist ID from URL."
|
||||
fi
|
||||
else
|
||||
curl -s "$url" | grep -o 'https://www.youtube.com/feeds/videos.xml?channel_id=[A-Za-z0-9_-]*' | sort | uniq
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Loading…
Add table
Add a link
Reference in a new issue