1
0
forked from bot/app

Add New function and layout for liteyuki_weather

This commit is contained in:
Envision 2024-08-11 01:40:26 +08:00
parent c3fc5d429b
commit 81a191f8ba
17 changed files with 278 additions and 74 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
.venv/
.idea/
.vscode/
.cache/
node_modules/
data/

View File

@ -169,3 +169,20 @@ async def get_airquality(
async with httpx.AsyncClient() as client:
resp = await client.get(url, params=params)
return resp.json()
async def get_astronomy(
key: str,
location: str,
date: str,
dev: bool = get_memory_data("is_dev", True),
) -> dict:
url_path = f"v7/astronomy/sun?"
url = dev_url + url_path if dev else com_url + url_path
params = {
"key" : key,
"location" : location,
"date" : date,
}
async with httpx.AsyncClient() as client:
resp = await client.get(url, params=params)
return resp.json()

View File

@ -1,3 +1,5 @@
import datetime
from nonebot import require, on_endswith
from nonebot.adapters import satori
from nonebot.adapters.onebot.v11 import MessageSegment
@ -50,6 +52,9 @@ async def get_weather_now_card(matcher: Matcher, event: T_MessageEvent, keyword:
qw_lang = get_qw_lang(ulang.lang_code)
key = get_config("weather_key")
is_dev = get_memory_data("weather.is_dev", True)
extra_info = get_config("weather_extra_info")
attr = get_config("weather_attr")
user: User = user_db.where_one(User(), "user_id = ?", event_utils.get_user_id(event), default=User())
# params
unit = user.profile.get("unit", "m")
@ -80,6 +85,7 @@ async def get_weather_now_card(matcher: Matcher, event: T_MessageEvent, keyword:
weather_daily = await get_weather_daily(key, location_data.id, lang=qw_lang, unit=unit, dev=is_dev)
weather_hourly = await get_weather_hourly(key, location_data.id, lang=qw_lang, unit=unit, dev=is_dev)
aqi = await get_airquality(key, location_data.id, lang=qw_lang, dev=is_dev)
weather_astronomy = await get_astronomy(key, location_data.id, date=datetime.datetime.now().strftime('%Y%m%d'), dev=is_dev)
image = await template2image(
template=get_path("templates/weather_now.html", abs_path=True),
@ -89,13 +95,17 @@ async def get_weather_now_card(matcher: Matcher, event: T_MessageEvent, keyword:
"unit": unit,
"lang": ulang.lang_code,
},
"weatherNow" : weather_now,
"weatherDaily" : weather_daily,
"weatherHourly": weather_hourly,
"aqi" : aqi,
"location" : location_data.dump(),
"localization" : get_local_data(ulang.lang_code),
"is_dev": 1 if is_dev else 0
"weatherNow" : weather_now,
"weatherDaily" : weather_daily,
"weatherHourly" : weather_hourly,
"aqi" : aqi,
"location" : location_data.dump(),
"localization" : get_local_data(ulang.lang_code),
"weatherAstronomy" : weather_astronomy,
"is_dev" : 1 if is_dev else 0,
"extra_info" : extra_info,
"attr" : attr
}
},
)

View File

@ -14,7 +14,7 @@
}
.icon {
/* icon 类img阴影*/
/* icon 类img阴影*/
filter: drop-shadow(1px 1px 10px #00000044);
}
@ -118,7 +118,7 @@
padding: 20px 10px;
}
.hourly-icon{
.hourly-icon {
width: 80%;
margin-bottom: 20px;
}
@ -167,18 +167,74 @@
height: 80px;
}
.daily-weather{
.daily-weather {
position: absolute;
left: 30%;
}
.daily-temperature{
.daily-temperature {
position: absolute;
left: 83%;
}
.daily-day, .daily-weather, .daily-temperature {
.daily-day,
.daily-weather,
.daily-temperature {
text-align: center;
color: var(--main-text-color);
font-size: 30px;
}
.ad-box {
margin-bottom: 20px;
img {
border-radius: 60px;
}
}
.sub-info {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
color: var(--main-text-color);
font-size: 40px;
align-items: center;
}
.sub-info>div {
display: flex;
align-items: center;
gap: 5px;
overflow: hidden;
padding-left: 20px;
/*要问就问html调svg为什么那么不友好*/
img {
transform: translateY(-80px);
/*自定义颜色*/
filter: drop-shadow(var(--main-text-color) 0 80px);
/*自定义透明度*/
opacity: 1;
padding-right: 10px;
}
}
.attribution-box {
margin: 0;
position: relative;
display: flex;
justify-content: center;
#attribution-info {
backdrop-filter: blur(10px);
padding: 0 5px 0;
background-color: rgba(0, 0, 0, 0.5);
font-size: 25px;
justify-content: space-between;
display: inline-flex;
word-wrap: break-word;
color: var(--sub-text-color);
text-align: center;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 48 48"><path fill="currentColor" d="M26.003 14.018c6.337 0 9.932 4.194 10.455 9.26h.16c4.078 0 7.384 3.298 7.384 7.365s-3.306 7.365-7.384 7.365h-21.23c-4.078 0-7.384-3.297-7.384-7.365s3.307-7.365 7.385-7.365h.16c.526-5.099 4.117-9.26 10.454-9.26M20 8a9.43 9.43 0 0 1 7.8 4.125a15 15 0 0 0-1.8-.107c-6.078 0-10.476 3.438-11.96 8.615l-.08.289l-.115.475l-.414.077a9.38 9.38 0 0 0-6.905 6.06a6.564 6.564 0 0 1 4.038-11.739h.142A9.44 9.44 0 0 1 20 8"/></svg>

After

Width:  |  Height:  |  Size: 531 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" color="currentColor"><path d="M12 22a5 5 0 0 0 3-9V5c0-.932 0-1.398-.152-1.766a2 2 0 0 0-1.082-1.082C13.4 2 12.932 2 12 2s-1.399 0-1.766.152a2 2 0 0 0-1.082 1.082C9 3.602 9 4.068 9 5v8a5 5 0 0 0 3 9"/><path d="M12 15a2 2 0 1 0 0 4a2 2 0 0 0 0-4m0 0V8"/></g></svg>

After

Width:  |  Height:  |  Size: 451 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 512 512"><path d="M271 38.6c-.3-.4-.7-.7-.9-1l-.1-.1c-3.6-3.4-8.5-5.5-13.9-5.5-5.5 0-10.4 2.1-13.9 5.5l-.1.1c-.3.3-.6.6-.9 1-6.1 6.3-13.8 14.4-22.4 24.1-17.4 19.7-38.6 46-58.5 76.8-33.4 51.8-62.9 116.1-64.1 183.1 0 1.3-.1 2.7-.1 4 0 19.7 3.9 38.5 10.9 55.8 4.1 10 9.2 19.4 15.2 28.2C150.7 452.4 200 480 256 480c88.4 0 160-68.7 160-153.4 0-127.9-105.2-247.4-145-288zM256 424c-15.8 0-30.7-3.7-43.9-10.1 65.9-14.4 118.4-64.7 135.8-129.5 5.2 12.1 8.2 25.5 8.2 39.6-.1 55.2-44.9 100-100.1 100z" fill="currentColor"/></svg>

After

Width:  |  Height:  |  Size: 595 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="currentColor" d="M12 3.001c3.169 0 4.966 2.097 5.227 4.63h.08A3.687 3.687 0 0 1 21 11.314a3.687 3.687 0 0 1-3.692 3.682h-.582l-.003.004h-.264a.8.8 0 0 1-.083.167l-1 1.5a.75.75 0 0 1-1.248-.832l.559-.839h-1.83l-.002.004h-.397a.8.8 0 0 1-.083.166l-1 1.5a.75.75 0 1 1-1.248-.831l.56-.839H8.986L8.985 15h-.527a.8.8 0 0 1-.084.167l-1 1.5a.75.75 0 0 1-1.248-.832l.56-.839A3.687 3.687 0 0 1 3 11.314A3.687 3.687 0 0 1 6.693 7.63h.08C7.035 5.08 8.831 3 12 3m0 1.498c-2.071 0-3.877 1.633-3.877 3.889c0 .357-.319.638-.684.638h-.69c-1.261 0-2.284 1.001-2.284 2.236S5.488 13.5 6.75 13.5h10.5c1.261 0 2.284-1.002 2.284-2.237s-1.023-2.236-2.284-2.236h-.69c-.365 0-.684-.28-.684-.638c0-2.285-1.806-3.89-3.877-3.89M7.126 18.834a.75.75 0 1 0 1.248.832l1-1.5a.75.75 0 1 0-1.248-.832zm4.208 1.04a.75.75 0 0 1-.208-1.04l1-1.5a.75.75 0 1 1 1.248.832l-1 1.5a.75.75 0 0 1-1.04.208"/></svg>

After

Width:  |  Height:  |  Size: 963 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" d="M20.693 17.33a9 9 0 1 0-17.386 0"/><path d="M12.766 15.582c.487.71.144 1.792-.766 2.417c-.91.626-2.043.558-2.53-.151c-.52-.756-2.314-5.007-3.403-7.637c-.205-.495.4-.911.79-.542c2.064 1.96 5.39 5.157 5.909 5.913Z"/><path stroke-linecap="round" d="M12 6v2m-6.364.636L7.05 10.05m11.314-1.414L16.95 10.05m3.743 7.28l-1.931-.518m-15.455.518l1.931-.518"/></g></svg>

After

Width:  |  Height:  |  Size: 530 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="currentColor" d="M3 12h4a5 5 0 0 1 5-5a5 5 0 0 1 5 5h4a1 1 0 0 1 1 1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1a1 1 0 0 1 1-1m12 0a3 3 0 0 0-3-3a3 3 0 0 0-3 3zM12 2l2.39 3.42C13.65 5.15 12.84 5 12 5s-1.65.15-2.39.42zM3.34 7l4.16-.35A7.2 7.2 0 0 0 5.94 8.5c-.44.74-.69 1.5-.83 2.29zm17.31 0l-1.77 3.79a7.02 7.02 0 0 0-2.38-4.15zm-7.94 9.3l3.11 3.11a.996.996 0 1 1-1.41 1.41L12 18.41l-2.41 2.41a.996.996 0 1 1-1.41-1.41l3.11-3.11c.21-.2.45-.3.71-.3s.5.1.71.3"/></svg>

After

Width:  |  Height:  |  Size: 549 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="currentColor" d="M3 12h4a5 5 0 0 1 5-5a5 5 0 0 1 5 5h4a1 1 0 0 1 1 1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1a1 1 0 0 1 1-1m12 0a3 3 0 0 0-3-3a3 3 0 0 0-3 3zM12 2l2.39 3.42C13.65 5.15 12.84 5 12 5s-1.65.15-2.39.42zM3.34 7l4.16-.35A7.2 7.2 0 0 0 5.94 8.5c-.44.74-.69 1.5-.83 2.29zm17.31 0l-1.77 3.79a7.02 7.02 0 0 0-2.38-4.15zm-7.94 13.71l3.11-3.11c.39-.39.39-1.03 0-1.42a.996.996 0 0 0-1.41 0L12 18.59l-2.41-2.41a.996.996 0 0 0-1.41 0c-.39.39-.39 1.03 0 1.42l3.11 3.11c.21.19.45.29.71.29s.5-.1.71-.29"/></svg>

After

Width:  |  Height:  |  Size: 595 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 16 16"><path fill="currentColor" d="M8.5 3a4 4 0 0 0-3.8 2.745a.5.5 0 1 1-.949-.313a5.002 5.002 0 0 1 9.654.595A3 3 0 0 1 13 12H4.5a.5.5 0 0 1 0-1H13a2 2 0 0 0 .001-4h-.026a.5.5 0 0 1-.5-.445A4 4 0 0 0 8.5 3M0 7.5A.5.5 0 0 1 .5 7h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5m2 2a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5m-2 4a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5"/></svg>

After

Width:  |  Height:  |  Size: 470 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 3v18m0-10l12-1V6L6 5m4 .5v5M14 6v4M4 21h4"/></svg>

After

Width:  |  Height:  |  Size: 245 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 48 48"><path fill="currentColor" d="M22.5 6a8.5 8.5 0 0 0-8.5 8.5a1.5 1.5 0 0 0 3 0a5.5 5.5 0 1 1 5.5 5.5h-17a1.5 1.5 0 0 0 0 3h17a8.5 8.5 0 0 0 0-17m14.904 12a6.5 6.5 0 0 0-6.306 4.924l-.053.212a1.5 1.5 0 1 0 2.91.728l.053-.213A3.5 3.5 0 0 1 37.404 21h.096a3.5 3.5 0 1 1 0 7h-32a1.5 1.5 0 0 0 0 3H30a3 3 0 1 1-2.77 4.154l-.095-.23a1.5 1.5 0 1 0-2.77 1.153l.097.23A6 6 0 1 0 35.197 31H37.5a6.5 6.5 0 1 0 0-13zM17.5 42a2.5 2.5 0 1 0 0-5a2.5 2.5 0 0 0 0 5M10 9.5a2.5 2.5 0 1 1-5 0a2.5 2.5 0 0 1 5 0M38.5 14a2.5 2.5 0 1 0 0-5a2.5 2.5 0 0 0 0 5"/></svg>

After

Width:  |  Height:  |  Size: 627 B

View File

@ -23,7 +23,10 @@ let weatherNow = data["weatherNow"]
let weatherDaily = data["weatherDaily"]
let weatherHourly = data["weatherHourly"]
let aqi = data["aqi"]
let weatherAstronomy = data["weatherAstronomy"]
let is_dev = data["is_dev"]
let attr = data["attr"]
let locationData = data["location"]
@ -35,10 +38,10 @@ if ("aqi" in aqi) {
if (item["defaultLocalAqi"]) {
document.getElementById("aqi-data").innerText = "AQI " + item["valueDisplay"] + " " + item["category"]
// 将(255,255,255)这种格式的颜色设置给css
if(is_dev == 1){
if (is_dev) {
//开发版
document.getElementById("aqi-dot").style.backgroundColor = "rgb(" + item["color"]['red'] + "," + item["color"]['green'] + "," + item["color"]['blue'] + "," + item["color"]['alpha'] + ")"
}else{
} else {
//正式版
document.getElementById("aqi-dot").style.backgroundColor = "rgb(" + item["color"] + ")"
}
@ -65,6 +68,33 @@ for (let id in templates) {
document.getElementById(id).innerText = templates[id]
}
subtemplates = {
"now-windDirect": weatherNow["now"]["windDir"] + " " + weatherNow["now"]["wind360"] + "°",
"now-windVelocity": "风矢 " + weatherNow["now"]["windScale"] + "级 " + weatherNow["now"]["windSpeed"] + "km/h",
"now-humidity": "湿度 " + weatherNow["now"]["humidity"] + "%",
"now-feelsLike": "体感 " + weatherNow["now"]["feelsLike"] + "°C",
"now-precip": "降水 " + weatherNow["now"]["precip"] + "mm",
"now-pressure": "气压 " + weatherNow["now"]["pressure"] + "hPa",
"vis": "能见 " + weatherNow["now"]["vis"] + "km",
"cloud ": "云量 " + (weatherNow["now"]["cloud"] == "" ? "无数据" : (weatherNow["now"]["cloud"] + "%")),
"astronomy-sunrise": "日出 " + get_time_hour(weatherAstronomy["sunrise"]),
"astronomy-sunset": "日落 " + get_time_hour(weatherAstronomy["sunset"])
}
let subItemDivTemplate = document.importNode(document.getElementById("sub-info-template").content, true);
let subItemDiv = subItemDivTemplate.querySelector(".sub-info");
for (let id in subtemplates) {
let element = subItemDiv.querySelector(`#${id}`);
if (element) {
element.innerText = subtemplates[id];
}
}
document.getElementById('sub-info').appendChild(subItemDiv);
let maxHourlyItem = 8
let percentWidth = 1 / (maxHourlyItem * 1.5) * 100
let hourlyStep = 2 // n小时一个数据
@ -126,7 +156,12 @@ weatherDaily['daily'].forEach(
)
function get_time_hour(fxTime) {
// fxTime 2024-05-03T02:00+/-08:00'
// fxTime 2024-05-03T02:00+/-08:00'
fxTime = fxTime.replace("-", "+")
return fxTime.split("T")[1].split("+")[0]
}
let attrinfo = document.getElementById('attribution-info');
if (!is_dev & !attr) attrinfo.parentElement.style.display = "none"
attrinfo.innerText = is_dev ? "Weather Service Drived by QWeather" : (attr ? attr : "Weather Service Drived by QWeather")

View File

@ -1,76 +1,151 @@
<!DOCTYPE html>
<html lang="zh" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>Liteyuki Status</title>
<link rel="stylesheet" href="./css/card.css">
<link rel="stylesheet" href="./css/fonts.css">
<link rel="stylesheet" href="css/weather_now.css">
<link rel="stylesheet" href="css/extra_info.css">
</head>
<!-- qw_icon: https://a.hecdn.net/img/common/icon/202106d/%d.png-->
<body>
<template id="hourly-item-template">
<div class="hourly-item">
<img class="hourly-icon icon" src="./img/qw_icon/101.png" alt="WeatherIcon">
<div class="hourly-temperature">90°</div>
<!-- <div class="hourly-windDir">None</div>-->
<div class="hourly-time">02:00</div>
</div>
</template>
<template id="hourly-item-template">
<div class="hourly-item">
<img class="hourly-icon icon" src="./img/qw_icon/101.png" alt="WeatherIcon">
<div class="hourly-temperature">90°</div>
<!-- <div class="hourly-windDir">None</div>-->
<div class="hourly-time">02:00</div>
</div>
</template>
<template id="daily-item-template">
<div class="daily-item">
<div class="daily-day">
周八
</div>
<div class="daily-weather">
小水
</div>
<img class="daily-icon icon-day icon" src="./img/qw_icon/101.png" alt="WeatherIcon">
<img class="daily-icon icon-night icon" src="./img/qw_icon/101.png" alt="WeatherIcon">
<div class="daily-temperature">
12°~23°
</div>
</div>
</template>
<template id="sub-info-template">
</template>
<div class="data-storage" id="data">{{ data | tojson }}</div>
<div class="info-box" id="weather-info">
<div id="detail-info">
<div id="time">2045-01-12 22:22:22</div>
<div id="adm">枫丹 白露 白露区</div>
<div id="city">白露区</div>
</div>
<div id="main-info">
<div id="main-left">
<img class="main-icon icon" src="./img/qw_icon/101.png" alt="WeatherIcon">
</div>
<div id="main-right">
<div id="temperature">
<div id="temperature-now">
90°
</div>
<div id="temperature-range">
10°~90°
</div>
<template id="daily-item-template">
<div class="daily-item">
<div class="daily-day">
周八
</div>
<div id="description">
示例天气
<div class="daily-weather">
小水
</div>
<img class="daily-icon icon-day icon" src="./img/qw_icon/101.png" alt="WeatherIcon">
<img class="daily-icon icon-night icon" src="./img/qw_icon/101.png" alt="WeatherIcon">
<div class="daily-temperature">
12°~23°
</div>
</div>
</div>
<div id="aqi">
<div id="aqi-dot"></div>
<div id="aqi-data"> AQI 114 优</div>
</div>
</div>
<div class="info-box" id="sub-info"></div>
<div class="info-box" id="hours-info"></div>
<div class="info-box" id="days-info"></div>
</template>
<template id="sub-info-template">
<div class="sub-info">
<div>
<img src="./img/svg/windDirect.svg" alt="SVG windDirect" width="60" height="60">
<div id="now-windDirect">
西北风 315°
</div>
</div>
<div><img src="./img/svg/windVelocity.svg" alt="SVG windVelocity" width="60" height="60">
<div id="now-windVelocity">
风矢 2级 10km/h
</div>
</div>
<div>
<img src="./img/svg/humidity.svg" alt="SVG humidity" width="60" height="60">
<div id="now-humidity">
湿度 45%
</div>
</div>
<div>
<img src="./img/svg/feelsLike.svg" alt="SVG feelsLike" width="60" height="60">
<div id="now-feelsLike">
体感 32°C
</div>
</div>
<div>
<img src="./img/svg/precip.svg" alt="SVG precip" width="60" height="60">
<div id="now-precip">
降水 0.0mm
</div>
</div>
<div>
<img src="./img/svg/pressure.svg" alt="SVG pressure" width="60" height="60">
<div id="now-pressure">
气压 979hPa
</div>
</div>
<div>
<img src="./img/svg/vis.svg" alt="SVG sunset" width="60" height="60">
<div id="vis">
能见 5km
</div>
</div>
<div>
<img src="./img/svg/cloud.svg" alt="SVG sunset" width="60" height="60">
<div id="cloud">
云量 50%
</div>
</div>
<div>
<img src="./img/svg/sunrise.svg" alt="SVG sunrise" width="60" height="60">
<div id="astronomy-sunrise">
日出 06:37
</div>
</div>
<div>
<img src="./img/svg/sunset.svg" alt="SVG sunset" width="60" height="60">
<div id="astronomy-sunset">
日落 19:01
</div>
</div>
</div>
</template>
<div class="data-storage" id="data">{{ data | tojson }}</div>
<div class="info-box" id="weather-info">
<div id="detail-info">
<div id="time">2045-01-12 22:22:22</div>
<div id="adm">枫丹 白露 白露区</div>
<div id="city">白露区</div>
</div>
<div id="main-info">
<div id="main-left">
<img class="main-icon icon" src="./img/qw_icon/101.png" alt="WeatherIcon">
</div>
<div id="main-right">
<div id="temperature">
<div id="temperature-now">
90°
</div>
<div id="temperature-range">
10°~90°
</div>
</div>
<div id="description">
示例天气
</div>
</div>
</div>
<div id="aqi">
<div id="aqi-dot"></div>
<div id="aqi-data"> AQI 114 优</div>
</div>
</div>
<div class="info-box" id="sub-info"></div>
<div class="info-box" id="hours-info"></div>
<div class="info-box" id="days-info"></div>
<div class="ad-box" hidden><img id="ad" src=""></div>
<script src="./js/card.js"></script>
<div class="attribution-box">
<div id="attribution-info"></div>
</div>
<script src="./js/weather_now.js"></script>
<script src="./js/card.js"></script>
<script src="./js/weather_now.js"></script>
</body>