baogutang-music/src/main/java/top/baogutang/music/service/impl/MusicInfoServiceImpl.java
2025-11-25 14:23:27 +08:00

232 lines
7.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package top.baogutang.music.service.impl;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import top.baogutang.music.dao.entity.MusicRecordEntity;
import top.baogutang.music.exceptions.BusinessException;
import top.baogutang.music.service.IMusicInfoService;
import top.baogutang.music.service.IMusicRecordService;
import top.baogutang.music.utils.CacheUtil;
import top.baogutang.music.utils.OkHttpUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import static top.baogutang.music.constants.CacheKey.KEY_MUSIC_TAG_TOKEN_PREFIX;
/**
*
* @description:
* @author: N1KO
* @date: 2025/01/23 : 14:53
*/
@Slf4j
@Service
@RefreshScope
public class MusicInfoServiceImpl implements IMusicInfoService {
@Resource
private IMusicRecordService musicRecordService;
@Resource
private RestTemplate restTemplate;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource(name = "commonExecutor")
private Executor commonExecutor;
@Value("${baogutang.music-tag.token}")
private String tokenUrl;
@Value("${baogutang.music-tag.token.param1:username}")
private String tokenParam1;
@Value("${baogutang.music-tag.token.value1:admin}")
private String tokenValue1;
@Value("${baogutang.music-tag.token.param2:password}")
private String tokenParam2;
@Value("${baogutang.music-tag.token.value2:admin}")
private String tokenValue2;
@Value(("${baogutang.music-tag.cover}"))
private String coverUrl;
@Override
public void getCover(String title, String artist, String album, HttpServletResponse response) {
MusicRecordEntity musicRecord = musicRecordService.queryByNameOrAlbumOrArtist(title, album, artist);
if (Objects.nonNull(musicRecord) && StringUtils.isNotBlank(musicRecord.getPic())) {
this.downloadPicAndResponse(musicRecord.getPic(), response);
return;
}
// 获取三方token
String token = CacheUtil.cacheOrSupply(KEY_MUSIC_TAG_TOKEN_PREFIX,
1L,
TimeUnit.DAYS,
redisTemplate,
this::geneToken,
new TypeReference<>() {
});
Map<String, String> headers = new HashMap<>();
headers.put("authorization", "jwt " + token);
headers.put("Content-Type", "application/json");
Map<String, Object> params = new HashMap<>();
if (StringUtils.isBlank(title)) {
params.put("title", album);
} else {
params.put("title", title);
}
params.put("artist", artist);
params.put("album", album);
InfoRes<List<MusicInfoRes>> res = this.queryInfo(headers, params);
if (Objects.isNull(res) || !Boolean.TRUE.equals(res.getResult()) || CollectionUtils.isEmpty(res.getData())) {
log.error("<<<<<<<<<<query info error>>>>>>>>>>");
return;
}
MusicInfoRes musicInfoRes = res.getData().get(0);
this.downloadPicAndResponse(musicInfoRes.getAlbumImg(), response);
}
private InfoRes<List<MusicInfoRes>> queryInfo(Map<String, String> headers, Map<String, Object> params) {
InfoRes<List<MusicInfoRes>> res = null;
try {
params.put("resource", "qmusic");
res = OkHttpUtil.post(coverUrl, headers, params, new TypeReference<>() {
});
if (Objects.isNull(res) || !Boolean.TRUE.equals(res.getResult()) || CollectionUtils.isEmpty(res.getData())) {
params.put("resource", "netease");
res = OkHttpUtil.post(coverUrl, headers, params, new TypeReference<>() {
});
}
} catch (Exception e) {
log.error("query music info error:{}", e.getMessage(), e);
return null;
}
return res;
}
private String geneToken() {
Map<String, String> params = new HashMap<>();
params.put(tokenParam1, tokenValue1);
params.put(tokenParam2, tokenValue2);
TokenRes tokenRes = null;
try {
tokenRes = OkHttpUtil.post(tokenUrl, params, new TypeReference<>() {
});
} catch (Exception e) {
log.error("<<<<<<<<<<获取token异常{}>>>>>>>>>>", e.getMessage(), e);
throw new BusinessException("获取token异常!");
}
if (Objects.nonNull(tokenRes) && Boolean.TRUE.equals(tokenRes.getResult())) {
return tokenRes.getToken();
}
throw new BusinessException("获取token异常!");
}
private void downloadPicAndResponse(String picUrl, HttpServletResponse response) {
// 获取响应实体
ResponseEntity<org.springframework.core.io.Resource> responseEntity = restTemplate.exchange(
picUrl,
HttpMethod.GET,
null,
org.springframework.core.io.Resource.class
);
// 设置Content-Type
MediaType contentType = responseEntity.getHeaders().getContentType();
if (contentType != null) {
response.setContentType(contentType.toString());
} else {
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
}
// 设置Content-Length如果可用
List<String> contentLength = responseEntity.getHeaders().get(HttpHeaders.CONTENT_LENGTH);
if (contentLength != null && !contentLength.isEmpty()) {
response.setHeader(HttpHeaders.CONTENT_LENGTH, contentLength.get(0));
}
if (Objects.isNull(responseEntity.getBody())) {
log.error("<<<<<<<<<<getCover error! url:{} response body is null>>>>>>>>>>", picUrl);
return;
}
try (InputStream inputStream = responseEntity.getBody().getInputStream();
OutputStream outputStream = response.getOutputStream()) {
// 数据传输
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
} catch (Exception e) {
log.error("getCover error!picUrl:{},message:{}", picUrl, e.getMessage(), e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
@Data
static class TokenRes {
private String token;
private Boolean result;
}
@Data
static class InfoRes<T> {
private Boolean result;
private String code;
private T data;
}
@Data
static class MusicInfoRes {
private String mid;
private String extra;
private String notice;
private String title;
private String singer;
private String album;
@JsonProperty("album_img")
private String albumImg;
private String artist;
}
}