🤡我知道您急,您先别急,这是有bug的,我还没改完,我就想换台设备来写

This commit is contained in:
2024-07-20 22:43:54 +08:00
parent d0d347e4e3
commit fe8f6bd443
120 changed files with 4965 additions and 3069 deletions

View File

@ -0,0 +1,15 @@
from nonebot.plugin import PluginMetadata
from nonebot import get_driver
__plugin_meta__ = PluginMetadata(
name="Minecraft工具箱",
description="一些Minecraft相关工具箱",
usage="我觉得你应该会用",
type="application",
homepage="https://github.com/snowykami/LiteyukiBot",
extra={
"liteyuki" : True,
"toggleable" : True,
"default_enable": True,
}
)

View File

@ -0,0 +1,20 @@
from nonebot.plugin import PluginMetadata
__author__ = "snowykami"
__plugin_meta__ = PluginMetadata(
name="轻雪包管理器v2",
description="详细看文档",
usage=(
"npm list\n"
"npm enable/disable <plugin_name>\n"
"npm search <keywords...>\n"
"npm install/uninstall <plugin_name>\n"
),
type="application",
homepage="https://github.com/snowykami/LiteyukiBot",
extra={
"liteyuki": True,
"toggleable" : False,
"default_enable" : False,
}
)

View File

@ -0,0 +1,27 @@
from nonebot.plugin import PluginMetadata
from nonebot import get_driver
from .qweather import *
__plugin_meta__ = PluginMetadata(
name="轻雪天气",
description="基于和风天气api的天气插件",
usage="",
type="application",
homepage="https://github.com/snowykami/LiteyukiBot",
extra={
"liteyuki" : True,
"toggleable" : True,
"default_enable": True,
}
)
from ...utils.base.data_manager import set_memory_data
driver = get_driver()
@driver.on_startup
async def _():
# 检查是否为开发者模式
is_dev = await check_key_dev(get_config("weather_key", ""))
set_memory_data("weather.is_dev", is_dev)

View File

@ -0,0 +1,171 @@
import aiohttp
from .qw_models import *
import httpx
from ...utils.base.data_manager import get_memory_data
from ...utils.base.language import Language
dev_url = "https://devapi.qweather.com/" # 开发HBa
com_url = "https://api.qweather.com/" # 正式环境
def get_qw_lang(lang: str) -> str:
if lang in ["zh-HK", "zh-TW"]:
return "zh-hant"
elif lang.startswith("zh"):
return "zh"
elif lang.startswith("en"):
return "en"
else:
return lang
async def check_key_dev(key: str) -> bool:
url = "https://api.qweather.com/v7/weather/now?"
params = {
"location": "101010100",
"key" : key,
}
async with aiohttp.ClientSession() as client:
resp = await client.get(url, params=params)
return (await resp.json()).get("code") != "200" # 查询不到付费数据为开发版
def get_local_data(ulang_code: str) -> dict:
"""
获取本地化数据
Args:
ulang_code:
Returns:
"""
ulang = Language(ulang_code)
return {
"monday" : ulang.get("weather.monday"),
"tuesday" : ulang.get("weather.tuesday"),
"wednesday": ulang.get("weather.wednesday"),
"thursday" : ulang.get("weather.thursday"),
"friday" : ulang.get("weather.friday"),
"saturday" : ulang.get("weather.saturday"),
"sunday" : ulang.get("weather.sunday"),
"today" : ulang.get("weather.today"),
"tomorrow" : ulang.get("weather.tomorrow"),
"day" : ulang.get("weather.day"),
"night" : ulang.get("weather.night"),
"no_aqi" : ulang.get("weather.no_aqi"),
}
async def city_lookup(
location: str,
key: str,
adm: str = "",
number: int = 20,
lang: str = "zh",
) -> CityLookup:
"""
通过关键字搜索城市信息
Args:
location:
key:
adm:
number:
lang: 可传入标准i18n语言代码如zh-CN、en-US等
Returns:
"""
url = "https://geoapi.qweather.com/v2/city/lookup?"
params = {
"location": location,
"adm" : adm,
"number" : number,
"key" : key,
"lang" : lang,
}
async with httpx.AsyncClient() as client:
resp = await client.get(url, params=params)
return CityLookup.parse_obj(resp.json())
async def get_weather_now(
key: str,
location: str,
lang: str = "zh",
unit: str = "m",
dev: bool = get_memory_data("is_dev", True),
) -> dict:
url_path = "v7/weather/now?"
url = dev_url + url_path if dev else com_url + url_path
params = {
"location": location,
"key" : key,
"lang" : lang,
"unit" : unit,
}
async with httpx.AsyncClient() as client:
resp = await client.get(url, params=params)
return resp.json()
async def get_weather_daily(
key: str,
location: str,
lang: str = "zh",
unit: str = "m",
dev: bool = get_memory_data("is_dev", True),
) -> dict:
url_path = "v7/weather/%dd?" % (7 if dev else 30)
url = dev_url + url_path if dev else com_url + url_path
params = {
"location": location,
"key" : key,
"lang" : lang,
"unit" : unit,
}
async with httpx.AsyncClient() as client:
resp = await client.get(url, params=params)
return resp.json()
async def get_weather_hourly(
key: str,
location: str,
lang: str = "zh",
unit: str = "m",
dev: bool = get_memory_data("is_dev", True),
) -> dict:
url_path = "v7/weather/%dh?" % (24 if dev else 168)
url = dev_url + url_path if dev else com_url + url_path
params = {
"location": location,
"key" : key,
"lang" : lang,
"unit" : unit,
}
async with httpx.AsyncClient() as client:
resp = await client.get(url, params=params)
return resp.json()
async def get_airquality(
key: str,
location: str,
lang: str,
pollutant: bool = False,
station: bool = False,
dev: bool = get_memory_data("is_dev", True),
) -> dict:
url_path = f"airquality/v1/now/{location}?"
url = dev_url + url_path if dev else com_url + url_path
params = {
"key" : key,
"lang" : lang,
"pollutant": pollutant,
"station" : station,
}
async with httpx.AsyncClient() as client:
resp = await client.get(url, params=params)
return resp.json()

View File

@ -0,0 +1,62 @@
from src.utils.base.data import LiteModel
class Location(LiteModel):
name: str = ""
id: str = ""
lat: str = ""
lon: str = ""
adm2: str = ""
adm1: str = ""
country: str = ""
tz: str = ""
utcOffset: str = ""
isDst: str = ""
type: str = ""
rank: str = ""
fxLink: str = ""
sources: str = ""
license: str = ""
class CityLookup(LiteModel):
code: str = ""
location: list[Location] = [Location()]
class Now(LiteModel):
obsTime: str = ""
temp: str = ""
feelsLike: str = ""
icon: str = ""
text: str = ""
wind360: str = ""
windDir: str = ""
windScale: str = ""
windSpeed: str = ""
humidity: str = ""
precip: str = ""
pressure: str = ""
vis: str = ""
cloud: str = ""
dew: str = ""
sources: str = ""
license: str = ""
class WeatherNow(LiteModel):
code: str = ""
updateTime: str = ""
fxLink: str = ""
now: Now = Now()
class Daily(LiteModel):
pass
class WeatherDaily(LiteModel):
code: str = ""
updateTime: str = ""
fxLink: str = ""
daily: list[str] = []

View File

@ -0,0 +1,101 @@
from nonebot import require, on_endswith
from nonebot.adapters import satori
from nonebot.adapters.onebot.v11 import MessageSegment
from nonebot.internal.matcher import Matcher
from src.utils.base.config import get_config
from src.utils.base.ly_typing import T_MessageEvent
from .qw_api import *
from src.utils.base.data_manager import User, user_db
from src.utils.base.language import Language, get_user_lang
from src.utils.base.resource import get_path
from src.utils.message.html_tool import template2image
from src.utils import event as event_utils
require("nonebot_plugin_alconna")
from nonebot_plugin_alconna import on_alconna, Alconna, Args, MultiVar, Arparma, UniMessage
wx_alc = on_alconna(
aliases={"天气"},
command=Alconna(
"weather",
Args["keywords", MultiVar(str), []],
),
)
@wx_alc.handle()
async def _(result: Arparma, event: T_MessageEvent, matcher: Matcher):
"""await alconna.send("weather", city)"""
kws = result.main_args.get("keywords")
image = await get_weather_now_card(matcher, event, kws)
await wx_alc.finish(UniMessage.image(raw=image))
@on_endswith(("天气", "weather")).handle()
async def _(event: T_MessageEvent, matcher: Matcher):
"""await alconna.send("weather", city)"""
# kws = event.message.extract_plain_text()
kws = event.get_plaintext()
image = await get_weather_now_card(matcher, event, [kws.replace("天气", "").replace("weather", "")], False)
if isinstance(event, satori.event.Event):
await matcher.finish(satori.MessageSegment.image(raw=image, mime="image/png"))
else:
await matcher.finish(MessageSegment.image(image))
async def get_weather_now_card(matcher: Matcher, event: T_MessageEvent, keyword: list[str], tip: bool = True):
ulang = get_user_lang(event_utils.get_user_id(event))
qw_lang = get_qw_lang(ulang.lang_code)
key = get_config("weather_key")
is_dev = get_memory_data("weather.is_dev", True)
user: User = user_db.where_one(User(), "user_id = ?", event_utils.get_user_id(event), default=User())
# params
unit = user.profile.get("unit", "m")
stored_location = user.profile.get("location", None)
if not key:
await matcher.finish(ulang.get("weather.no_key") if tip else None)
if keyword:
if len(keyword) >= 2:
adm = keyword[0]
city = keyword[-1]
else:
adm = ""
city = keyword[0]
city_info = await city_lookup(city, key, adm=adm, lang=qw_lang)
city_name = " ".join(keyword)
else:
if not stored_location:
await matcher.finish(ulang.get("liteyuki.invalid_command", TEXT="location") if tip else None)
city_info = await city_lookup(stored_location, key, lang=qw_lang)
city_name = stored_location
if city_info.code == "200":
location_data = city_info.location[0]
else:
await matcher.finish(ulang.get("weather.city_not_found", CITY=city_name) if tip else None)
weather_now = await get_weather_now(key, location_data.id, lang=qw_lang, unit=unit, dev=is_dev)
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)
image = await template2image(
template=get_path("templates/weather_now.html", abs_path=True),
templates={
"data": {
"params" : {
"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)
}
},
)
return image