Compare commits

...

5 commits

Author SHA1 Message Date
8168566498
ci: add workflows
All checks were successful
CI / Test (push) Successful in 1m50s
2024-03-23 02:43:18 +01:00
b30b9d7b9f
chore: add git-cliff 2024-03-23 02:36:33 +01:00
7d153499ed
chore: update dependencies 2024-03-23 02:35:46 +01:00
4282889ebe
feat: add search function 2024-03-23 02:35:25 +01:00
9958c57c73
test: update tests 2024-03-23 02:33:31 +01:00
9 changed files with 292 additions and 70 deletions

19
.gitea/workflows/ci.yaml Normal file
View file

@ -0,0 +1,19 @@
name: CI
on: [push, pull_request]
jobs:
Test:
runs-on: cimaster-latest
steps:
- name: 📦 Checkout repository
uses: actions/checkout@v3
- name: 🦀 Setup Rust cache
uses: https://github.com/Swatinem/rust-cache@v2
with:
cache-on-failure: "true"
- name: 📎 Clippy
run: cargo clippy --all -- -D warnings
- name: 🧪 Test
run: cargo test --workspace

View file

@ -0,0 +1,38 @@
name: Release
on:
push:
tags:
- "*/v*.*.*"
jobs:
Release:
runs-on: cimaster-latest
steps:
- name: 📦 Checkout repository
uses: actions/checkout@v3
- name: Get variables
run: |
git fetch --tags --force #the checkout action does not load the tag message
echo "CRATE=$(echo '${{ github.ref_name }}' | awk 'BEGIN{RS="/"} NR==1{print}')" >> "$GITHUB_ENV"
echo "CRATE_VERSION=$(echo '${{ github.ref_name }}' | awk 'BEGIN{RS="/"} NR==2{print}')" >> "$GITHUB_ENV"
{
echo 'CHANGELOG<<END_OF_FILE'
git show -s --format=%N "${{ github.ref_name }}" | tail -n +4 | awk 'BEGIN{RS="-----BEGIN PGP SIGNATURE-----"} NR==1{printf $0}'
echo END_OF_FILE
} >> "$GITHUB_ENV"
- name: 📤 Publish crate on code.thetadev.de
run: |
mkdir -p ~/.cargo
printf '[registries.thetadev]\nindex = "https://code.thetadev.de/ThetaDev/_cargo-index.git"\ntoken = "Bearer ${{ secrets.TOKEN_GITEA }}"\n' >> ~/.cargo/config.toml
sed -i "s/^musixmatch-.*=\s*{/\0 registry = \"thetadev\",/g" Cargo.toml
cargo publish --registry thetadev --package "${{ env.CRATE }}" --allow-dirty
git restore Cargo.toml
- name: 🎉 Publish release
uses: https://gitea.com/actions/release-action@main
with:
title: "${{ env.CRATE }} ${{ env.CRATE_VERSION }}"
body: "${{ env.CHANGELOG }}"

View file

@ -1,11 +0,0 @@
steps:
test:
image: rust:latest
secrets:
- musixmatch_email
- musixmatch_password
commands:
- rustup component add rustfmt clippy
- cargo fmt --all --check
- cargo clippy --all -- -D warnings
- cargo test --workspace

View file

@ -12,6 +12,9 @@ include = ["/src", "README.md", "LICENSE"]
[workspace] [workspace]
members = [".", "cli"] members = [".", "cli"]
[workspace.dependencies]
musixmatch-inofficial = { version = "0.1.0", path = ".", default-features = false }
[features] [features]
default = ["default-tls"] default = ["default-tls"]
@ -24,7 +27,7 @@ rustls-tls-webpki-roots = ["reqwest/rustls-tls-webpki-roots"]
rustls-tls-native-roots = ["reqwest/rustls-tls-native-roots"] rustls-tls-native-roots = ["reqwest/rustls-tls-native-roots"]
[dependencies] [dependencies]
reqwest = { version = "0.11.11", default-features = false, features = [ reqwest = { version = "0.12.0", default-features = false, features = [
"json", "json",
"gzip", "gzip",
] } ] }
@ -42,7 +45,7 @@ time = { version = "0.3.15", features = [
hmac = "0.12.1" hmac = "0.12.1"
sha1 = "0.10.5" sha1 = "0.10.5"
rand = "0.8.5" rand = "0.8.5"
base64 = "0.21.0" base64 = "0.22.0"
[dev-dependencies] [dev-dependencies]
ctor = "0.2.0" ctor = "0.2.0"

44
Justfile Normal file
View file

@ -0,0 +1,44 @@
test:
cargo test
release crate="musixmatch-inofficial":
#!/usr/bin/env bash
set -e
CRATE="{{crate}}"
INCLUDES='--include-path README.md --include-path LICENSE --include-path Cargo.toml'
CHANGELOG="CHANGELOG.md"
if [ "$CRATE" = "musixmatch-inofficial" ]; then
INCLUDES="$INCLUDES --include-path src/** --include-path tests/** --include-path testfiles/**"
else
if [ ! -d "$CRATE" ]; then
echo "$CRATE does not exist."; exit 1
fi
INCLUDES="$INCLUDES --include-path $CRATE/**"
CHANGELOG="$CRATE/$CHANGELOG"
CRATE="musixmatch-$CRATE" # Add crate name prefix
fi
VERSION=$(cargo pkgid --package "$CRATE" | tr '#@' '\n' | tail -n 1)
TAG="${CRATE}/v${VERSION}"
echo "Releasing $TAG:"
if git rev-parse "$TAG" >/dev/null 2>&1; then echo "version tag $TAG already exists"; exit 1; fi
CLIFF_ARGS="--tag v${VERSION} --tag-pattern ${CRATE}/* --unreleased $INCLUDES"
echo "git-cliff $CLIFF_ARGS"
if [ -f "$CHANGELOG" ]; then
git-cliff $CLIFF_ARGS --prepend "$CHANGELOG"
else
git-cliff $CLIFF_ARGS --output "$CHANGELOG"
fi
editor "$CHANGELOG"
git add "$CHANGELOG"
git commit -m "chore(release): release $CRATE v$VERSION"
awk 'BEGIN{RS="(^|\n)## [^\n]+\n*"} NR==2 { print }' "$CHANGELOG" | git tag -as -F - --cleanup whitespace "$TAG"
echo "🚀 Run 'git push origin $TAG' to publish"

View file

@ -18,7 +18,7 @@ rustls-tls-webpki-roots = ["musixmatch-inofficial/rustls-tls-webpki-roots"]
rustls-tls-native-roots = ["musixmatch-inofficial/rustls-tls-native-roots"] rustls-tls-native-roots = ["musixmatch-inofficial/rustls-tls-native-roots"]
[dependencies] [dependencies]
musixmatch-inofficial = { path = "../" } musixmatch-inofficial.workspace = true
tokio = { version = "1.20.0", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.20.0", features = ["macros", "rt-multi-thread"] }
id3 = "1.3.0" id3 = "1.3.0"
mp3-duration = "0.1.10" mp3-duration = "0.1.10"

View file

@ -28,6 +28,20 @@ enum Commands {
#[command(subcommand)] #[command(subcommand)]
command: FileCommands, command: FileCommands,
}, },
#[group(required = true)]
Search {
/// Track name
#[clap(short, long)]
name: Option<String>,
/// Artist
#[clap(short, long)]
artist: Option<String>,
/// Lyrics
#[clap(short, long)]
lyrics: Option<String>,
/// Search query
query: Option<Vec<String>>,
},
} }
#[derive(Subcommand)] #[derive(Subcommand)]
@ -319,6 +333,42 @@ async fn run(cli: Cli) -> Result<()> {
println!("{}", subtitles.subtitle_body); println!("{}", subtitles.subtitle_body);
} }
}, },
Commands::Search {
query,
name,
artist,
lyrics,
} => {
let mut sb = mxm
.track_search()
.s_track_rating(musixmatch_inofficial::models::SortOrder::Desc);
let querystr;
if let Some(q) = &query {
querystr = q.join(" ");
sb = sb.q(&querystr);
}
if let Some(n) = &name {
sb = sb.q_track(n);
}
if let Some(a) = &artist {
sb = sb.q_artist(a);
}
if let Some(l) = &lyrics {
sb = sb.q_lyrics(l);
}
let tracks = sb.send(20, 0).await?;
for t in tracks {
println!(
"{} - {} ({}) ISRC'{}' <https://musixmatch.com/lyrics/{}>",
t.track_name,
t.artist_name,
t.first_release_date.map(|d| d.year()).unwrap_or_default(),
t.track_isrc.unwrap_or_default(),
t.commontrack_vanity_id
);
}
}
}; };
Ok(()) Ok(())
} }

99
cliff.toml Normal file
View file

@ -0,0 +1,99 @@
# git-cliff ~ default configuration file
# https://git-cliff.org/docs/configuration
#
# Lines starting with "#" are comments.
# Configuration options are organized into tables and keys.
# See documentation for more information on available options.
[changelog]
# changelog header
header = """
# Changelog\n
All notable changes to this project will be documented in this file.\n
"""
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
{% set repo_url = "https://code.thetadev.de/ThetaDev/rustypipe" %}\
{% if version %}\
{%if previous.version %}\
## [{{ version }}]({{ repo_url }}/compare/{{ previous.version }}..{{ version }})\
{% else %}\
## {{ version }}\
{% endif %} - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [unreleased]
{% endif %}\
{% if previous.version %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**] {% endif %}\
{{ commit.message | upper_first }} - \
([{{ commit.id | truncate(length=7, end="") }}]({{ repo_url }}/commit/{{ commit.id }}))\
{% endfor %}
{% endfor %}\
{% else %}
Initial release
{% endif %}\n
"""
# template for the changelog footer
footer = """
<!-- generated by git-cliff -->
"""
# remove the leading and trailing s
trim = true
# postprocessors
postprocessors = [
# { pattern = '<REPO>', replace = "https://github.com/orhun/git-cliff" }, # replace repository URL
]
[git]
# parse the commits based on https://www.conventionalcommits.org
conventional_commits = true
# filter out the commits that are not conventional
filter_unconventional = true
# process each line of a commit as an individual commit
split_commits = false
# regex for preprocessing the commit messages
commit_preprocessors = [
# Replace issue numbers
#{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](<REPO>/issues/${2}))"},
# Check spelling of the commit with https://github.com/crate-ci/typos
# If the spelling is incorrect, it will be automatically fixed.
#{ pattern = '.*', replace_command = 'typos --write-changes -' },
]
# regex for parsing and grouping commits
commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
{ message = "^chore\\(release\\): prepare for", skip = true },
{ message = "^chore\\(pr\\)", skip = true },
{ message = "^chore\\(pull\\)", skip = true },
{ message = "^chore", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
{ message = "^ci", skip = true },
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
{ message = "^revert", group = "<!-- 9 -->◀️ Revert" },
]
# protect breaking changes from being skipped due to matching a skipping commit_parser
protect_breaking_commits = false
# filter out the commits that are not matched by commit parsers
filter_commits = false
# regex for matching git tags
# tag_pattern = "v[0-9].*"
# regex for skipping tags
# skip_tags = ""
# regex for ignoring tags
# ignore_tags = ""
# sort the tags topologically
topo_order = false
# sort the commits inside sections by oldest/newest order
sort_commits = "oldest"
# limit the number of commits included in the changelog.
# limit_commits = 42

View file

@ -89,18 +89,9 @@ mod album {
); );
assert_eq!(album.album_vanity_id, "410698/Gangnam-Style-Single"); assert_eq!(album.album_vanity_id, "410698/Gangnam-Style-Single");
assert!(album.updated_time > datetime!(2022-6-3 0:00 UTC)); assert!(album.updated_time > datetime!(2022-6-3 0:00 UTC));
assert_eq!( assert_imgurl(&album.album_coverart_100x100, "/26544045.jpg");
album.album_coverart_100x100.unwrap(), assert_imgurl(&album.album_coverart_350x350, "/26544045_350_350.jpg");
"https://s.mxmcdn.net/images-storage/albums/5/4/0/4/4/5/26544045.jpg" assert_imgurl(&album.album_coverart_500x500, "/26544045_500_500.jpg");
);
assert_eq!(
album.album_coverart_350x350.unwrap(),
"https://s.mxmcdn.net/images-storage/albums/5/4/0/4/4/5/26544045_350_350.jpg"
);
assert_eq!(
album.album_coverart_500x500.unwrap(),
"https://s.mxmcdn.net/images-storage/albums/5/4/0/4/4/5/26544045_500_500.jpg"
);
} }
#[tokio::test] #[tokio::test]
@ -333,18 +324,9 @@ mod track {
"650e7db6-b795-4eb5-a702-5ea2fc46c848" "650e7db6-b795-4eb5-a702-5ea2fc46c848"
); );
assert_eq!(track.artist_name, "Lady Gaga"); assert_eq!(track.artist_name, "Lady Gaga");
assert_eq!( assert_imgurl(&track.album_coverart_100x100, "/26319636.jpg");
track.album_coverart_100x100.unwrap(), assert_imgurl(&track.album_coverart_350x350, "/26319636_350_350.jpg");
"https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636.jpg" assert_imgurl(&track.album_coverart_500x500, "/26319636_500_500.jpg");
);
assert_eq!(
track.album_coverart_350x350.unwrap(),
"https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636_350_350.jpg"
);
assert_eq!(
track.album_coverart_500x500.unwrap(),
"https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636_500_500.jpg"
);
assert_eq!(track.commontrack_vanity_id, "Lady-Gaga/poker-face-1"); assert_eq!(track.commontrack_vanity_id, "Lady-Gaga/poker-face-1");
let first_release = track.first_release_date.unwrap(); let first_release = track.first_release_date.unwrap();
assert_eq!(first_release.date(), date!(2008 - 1 - 1)); assert_eq!(first_release.date(), date!(2008 - 1 - 1));
@ -414,18 +396,9 @@ mod track {
assert_eq!(track.album_name, "Black Mamba"); assert_eq!(track.album_name, "Black Mamba");
assert_eq!(track.artist_id, 46970441); assert_eq!(track.artist_id, 46970441);
assert_eq!(track.artist_name, "aespa"); assert_eq!(track.artist_name, "aespa");
assert_eq!( assert_imgurl(&track.album_coverart_100x100, "/52156772.jpg");
track.album_coverart_100x100.unwrap(), assert_imgurl(&track.album_coverart_350x350, "/52156772_350_350.jpg");
"https://s.mxmcdn.net/images-storage/albums5/2/7/7/6/5/1/52156772.jpg" assert_imgurl(&track.album_coverart_500x500, "/52156772_500_500.jpg");
);
assert_eq!(
track.album_coverart_350x350.unwrap(),
"https://s.mxmcdn.net/images-storage/albums5/2/7/7/6/5/1/52156772_350_350.jpg"
);
assert_eq!(
track.album_coverart_500x500.unwrap(),
"https://s.mxmcdn.net/images-storage/albums5/2/7/7/6/5/1/52156772_500_500.jpg"
);
assert_eq!(track.commontrack_vanity_id, "aespa/Black-Mamba"); assert_eq!(track.commontrack_vanity_id, "aespa/Black-Mamba");
let release_date = track.first_release_date.unwrap(); let release_date = track.first_release_date.unwrap();
@ -491,18 +464,9 @@ mod track {
"650e7db6-b795-4eb5-a702-5ea2fc46c848" "650e7db6-b795-4eb5-a702-5ea2fc46c848"
); );
assert_eq!(track.artist_name, "Lady Gaga"); assert_eq!(track.artist_name, "Lady Gaga");
assert_eq!( assert_imgurl(&track.album_coverart_100x100, "/26319636.jpg");
track.album_coverart_100x100.unwrap(), assert_imgurl(&track.album_coverart_350x350, "/26319636_350_350.jpg");
"https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636.jpg" assert_imgurl(&track.album_coverart_500x500, "/26319636_500_500.jpg");
);
assert_eq!(
track.album_coverart_350x350.unwrap(),
"https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636_350_350.jpg"
);
assert_eq!(
track.album_coverart_500x500.unwrap(),
"https://s.mxmcdn.net/images-storage/albums/6/3/6/9/1/3/26319636_500_500.jpg"
);
assert_eq!(track.commontrack_vanity_id, "Lady-Gaga/poker-face-1"); assert_eq!(track.commontrack_vanity_id, "Lady-Gaga/poker-face-1");
let first_release = track.first_release_date.unwrap(); let first_release = track.first_release_date.unwrap();
assert_eq!(first_release.date(), date!(2008 - 1 - 1)); assert_eq!(first_release.date(), date!(2008 - 1 - 1));
@ -702,16 +666,20 @@ mod lyrics {
// dbg!(&lyrics); // dbg!(&lyrics);
assert_eq!(lyrics.lyrics_id, 25947036); assert_eq!(lyrics.lyrics_id, 34583240);
assert!(!lyrics.instrumental); assert!(!lyrics.instrumental);
assert!(!lyrics.explicit); assert!(!lyrics.explicit);
assert!(lyrics assert!(
lyrics
.lyrics_body .lyrics_body
.starts_with("Eyes, in the sky, gazing far into the night\n")); .starts_with("Eyes in the sky gazing far into the night\n"),
"got: {}",
lyrics.lyrics_body
);
assert_eq!(lyrics.lyrics_language.unwrap(), "en"); assert_eq!(lyrics.lyrics_language.unwrap(), "en");
assert_eq!(lyrics.lyrics_language_description.unwrap(), "English"); assert_eq!(lyrics.lyrics_language_description.unwrap(), "English");
let copyright = lyrics.lyrics_copyright.unwrap(); let copyright = lyrics.lyrics_copyright.unwrap();
assert!(copyright.contains("Kim Jeffeson"), "copyright: {copyright}",); assert!(copyright.contains("Jesse Warren"), "copyright: {copyright}",);
assert!(lyrics.updated_time > datetime!(2021-6-3 0:00 UTC)); assert!(lyrics.updated_time > datetime!(2021-6-3 0:00 UTC));
} }
@ -851,12 +819,12 @@ mod subtitles {
// dbg!(&subtitle); // dbg!(&subtitle);
assert_eq!(subtitle.subtitle_id, 36913312); assert_eq!(subtitle.subtitle_id, 35340319);
assert_eq!(subtitle.subtitle_language.unwrap(), "en"); assert_eq!(subtitle.subtitle_language.unwrap(), "en");
assert_eq!(subtitle.subtitle_language_description.unwrap(), "English"); assert_eq!(subtitle.subtitle_language_description.unwrap(), "English");
let copyright = subtitle.lyrics_copyright.unwrap(); let copyright = subtitle.lyrics_copyright.unwrap();
assert!(copyright.contains("Kim Jeffeson"), "copyright: {copyright}",); assert!(copyright.contains("Jesse Warren"), "copyright: {copyright}",);
assert_eq!(subtitle.subtitle_length, 315); assert_eq!(subtitle.subtitle_length, 316);
assert!(subtitle.updated_time > datetime!(2021-6-30 0:00 UTC)); assert!(subtitle.updated_time > datetime!(2021-6-30 0:00 UTC));
} }
@ -993,3 +961,15 @@ mod translation {
assert_eq!(subtitles_trans.to_ttml().trim(), expected_ttml.trim()); assert_eq!(subtitles_trans.to_ttml().trim(), expected_ttml.trim());
} }
} }
#[track_caller]
fn assert_imgurl(url: &Option<String>, ends_with: &str) {
assert!(
url.as_deref().is_some_and(
|url| url.starts_with("https://s.mxmcdn.net/images-storage/")
&& url.ends_with(ends_with)
),
"expected url ending with {ends_with}\ngot {:?}",
url
);
}