mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-11-28 04:06:28 +08:00
Rewrite weather commands
This commit is contained in:
parent
5cbbac7155
commit
33fa1f13d8
@ -294,8 +294,11 @@ hub = CommandHub()
|
||||
|
||||
def split_args(maxsplit=0):
|
||||
def decorator(func):
|
||||
def wrapper(args_text, *args, **kwargs):
|
||||
args_list = list(filter(lambda arg: arg, re.split('|'.join(_command_args_seps), args_text, maxsplit)))
|
||||
def wrapper(argument, *args, **kwargs):
|
||||
if isinstance(argument, (list, tuple)):
|
||||
args_list = list(argument)
|
||||
else:
|
||||
args_list = list(filter(lambda arg: arg, re.split('|'.join(_command_args_seps), argument, maxsplit)))
|
||||
return func(args_list, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
@ -65,8 +65,8 @@ def short_url(args_text, ctx_msg):
|
||||
core.echo('生成失败,可能因为链接格式错误或服务器连接不上', ctx_msg)
|
||||
|
||||
|
||||
@cr.register('weather')
|
||||
@cr.register('天气', '查天气')
|
||||
# @cr.register('weather')
|
||||
# @cr.register('天气', '查天气')
|
||||
def weather(args_text, ctx_msg):
|
||||
city = args_text.strip()
|
||||
if not city:
|
||||
|
191
commands/weather.py
Normal file
191
commands/weather.py
Normal file
@ -0,0 +1,191 @@
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
import requests
|
||||
import jieba
|
||||
|
||||
from command import CommandRegistry, split_args
|
||||
from commands import core
|
||||
from little_shit import get_source
|
||||
from interactive import *
|
||||
|
||||
__registry__ = cr = CommandRegistry()
|
||||
|
||||
_api_key = os.environ.get('HEWEATHER_API_KEY')
|
||||
_base_api_url = 'https://free-api.heweather.com/v5'
|
||||
_search_api_url = _base_api_url + '/search'
|
||||
_forecast_api_url = _base_api_url + '/forecast'
|
||||
_now_api_url = _base_api_url + '/now'
|
||||
_suggestion_api_url = _base_api_url + '/suggestion'
|
||||
|
||||
_cmd_weather = 'weather.weather'
|
||||
_cmd_suggestion = 'weather.suggestion'
|
||||
|
||||
_weekday_string = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||||
|
||||
|
||||
@cr.register('weather')
|
||||
@cr.register('天气', '查天气', '天气预报', '查天气预报')
|
||||
@split_args()
|
||||
def weather(args, ctx_msg, allow_interactive=True):
|
||||
source = get_source(ctx_msg)
|
||||
if allow_interactive and (len(args) < 1 or not args[0].startswith('CN') or has_session(source, _cmd_weather)):
|
||||
# Be interactive
|
||||
return _do_interactively(_cmd_weather, weather, args, ctx_msg, source)
|
||||
|
||||
city_id = args[0]
|
||||
session = requests.Session()
|
||||
params = {'city': city_id, 'key': _api_key}
|
||||
text = ''
|
||||
|
||||
# Get real-time weather
|
||||
data_now = session.get(_now_api_url, params=params).json()
|
||||
if data_now and 'HeWeather5' in data_now and data_now['HeWeather5'][0].get('status') == 'ok':
|
||||
now = data_now['HeWeather5'][0]['now']
|
||||
text += '实时:\n%s,气温%s˚C,体感温度%s˚C,%s%s级,能见度%skm' \
|
||||
% (now['cond']['txt'], now['tmp'], now['fl'], now['wind']['dir'], now['wind']['sc'], now['vis'])
|
||||
|
||||
# Get forecast
|
||||
data_forecast = session.get(_forecast_api_url, params=params).json()
|
||||
if data_forecast and 'HeWeather5' in data_forecast and data_forecast['HeWeather5'][0].get('status') == 'ok':
|
||||
daily_forecast = data_forecast['HeWeather5'][0]['daily_forecast']
|
||||
text += '\n\n预报:\n'
|
||||
|
||||
for forecast in daily_forecast:
|
||||
d = datetime.strptime(forecast['date'], '%Y-%m-%d')
|
||||
text += '%d月%d日%s,' % (d.month, d.day, _weekday_string[d.weekday()])
|
||||
|
||||
cond_d = forecast['cond']['txt_d']
|
||||
cond_n = forecast['cond']['txt_n']
|
||||
text += cond_d + ('转' + cond_n if cond_d != cond_n else '') + ','
|
||||
|
||||
text += forecast['tmp']['min'] + '~' + forecast['tmp']['max'] + '°C,'
|
||||
text += forecast['wind']['dir'] + forecast['wind']['sc'] + '级,'
|
||||
text += '降雨概率%s%%' % forecast['pop']
|
||||
text += '\n'
|
||||
|
||||
text = text.rstrip()
|
||||
if text:
|
||||
core.echo(text, ctx_msg)
|
||||
else:
|
||||
core.echo('查询失败了,请稍后再试哦~', ctx_msg)
|
||||
|
||||
|
||||
@cr.register('suggestion')
|
||||
@cr.register('生活指数', '生活建议', '天气建议')
|
||||
@split_args()
|
||||
def suggestion(args, ctx_msg, allow_interactive=True):
|
||||
source = get_source(ctx_msg)
|
||||
if allow_interactive and (len(args) < 1 or not args[0].startswith('CN') or has_session(source, _cmd_suggestion)):
|
||||
# Be interactive
|
||||
return _do_interactively(_cmd_suggestion, suggestion, args, ctx_msg, source)
|
||||
|
||||
city_id = args[0]
|
||||
session = requests.Session()
|
||||
params = {'city': city_id, 'key': _api_key}
|
||||
text = ''
|
||||
|
||||
# Get suggestion
|
||||
data_suggestion = session.get(_suggestion_api_url, params=params).json()
|
||||
if data_suggestion and 'HeWeather5' in data_suggestion and data_suggestion['HeWeather5'][0].get('status') == 'ok':
|
||||
data = data_suggestion['HeWeather5'][0]['suggestion']
|
||||
text += '生活指数:\n\n' \
|
||||
'舒适度:%s\n\n' \
|
||||
'洗车指数:%s\n\n' \
|
||||
'穿衣指数:%s\n\n' \
|
||||
'感冒指数:%s\n\n' \
|
||||
'运动指数:%s\n\n' \
|
||||
'旅游指数:%s\n\n' \
|
||||
'紫外线指数:%s' \
|
||||
% tuple([data[k]['txt'] for k in ('comf', 'cw', 'drsg', 'flu', 'sport', 'trav', 'uv')])
|
||||
|
||||
if text:
|
||||
core.echo(text, ctx_msg)
|
||||
else:
|
||||
core.echo('查询失败了,请稍后再试哦~', ctx_msg)
|
||||
|
||||
|
||||
_state_machines = {}
|
||||
|
||||
|
||||
def _do_interactively(command_name, func, args, ctx_msg, source):
|
||||
def ask_for_city(s, a, c):
|
||||
if len(a) > 0:
|
||||
if search_city(s, a, c):
|
||||
return True
|
||||
else:
|
||||
core.echo('你要查询哪个城市呢?', c)
|
||||
s.state += 1
|
||||
|
||||
def search_city(s, a, c):
|
||||
if len(a) < 1:
|
||||
core.echo('你输入的城市不正确哦,请重新发送命令~', c)
|
||||
return True
|
||||
|
||||
prov = None
|
||||
city = a[0]
|
||||
# Try to split province and city if possible
|
||||
tmp = jieba.lcut(city)
|
||||
if len(tmp) == 2:
|
||||
prov, city = tmp
|
||||
|
||||
resp = requests.get(_search_api_url, params={
|
||||
'city': city,
|
||||
'key': _api_key
|
||||
})
|
||||
data = resp.json()
|
||||
if resp.status_code == 200 and data and 'HeWeather5' in data:
|
||||
city_list = data['HeWeather5']
|
||||
if city_list[0].get('status') != 'ok':
|
||||
core.echo('没有找到你输入的城市哦,请重新发送命令~', c)
|
||||
return True
|
||||
|
||||
if prov:
|
||||
city_list = list(filter(lambda c: c['basic']['prov'] == prov, city_list))
|
||||
|
||||
s.data['city_list'] = city_list
|
||||
|
||||
if len(city_list) == 1:
|
||||
# Directly choose the first one
|
||||
choose_city(s, ['1'], c)
|
||||
return True
|
||||
|
||||
# Here comes more than one city with the same name
|
||||
core.echo(
|
||||
'找到 %d 个重名城市,请选择你要查询的那个,发送它的序号:\n\n' % len(city_list)
|
||||
+ '\n'.join(
|
||||
[str(i + 1) + '. ' + c['basic']['prov'] + c['basic']['city'] for i, c in enumerate(city_list)]
|
||||
),
|
||||
c
|
||||
)
|
||||
|
||||
s.state += 1
|
||||
|
||||
def choose_city(s, a, c):
|
||||
if len(a) != 1 or not a[0].isdigit():
|
||||
core.echo('你输入的序号不正确哦,请重新发送命令~', c)
|
||||
return True
|
||||
|
||||
choice = int(a[0]) - 1 # Should be from 0 to len(city_list) - 1
|
||||
city_list = s.data['city_list']
|
||||
if choice < 0 or choice >= len(city_list):
|
||||
core.echo('你输入的序号超出范围了,请重新发送命令~', c)
|
||||
return True
|
||||
|
||||
city_id = city_list[choice]['basic']['id']
|
||||
# sess.data['func']([city_id], c, allow_interactive=False)
|
||||
func([city_id], c, allow_interactive=False)
|
||||
return True
|
||||
|
||||
if command_name not in _state_machines:
|
||||
_state_machines[command_name] = (
|
||||
ask_for_city, # 0
|
||||
search_city, # 1
|
||||
choose_city # 2
|
||||
)
|
||||
|
||||
sess = get_session(source, command_name)
|
||||
sess.data['func'] = func
|
||||
if _state_machines[command_name][sess.state](sess, args, ctx_msg):
|
||||
# Done
|
||||
remove_session(source, command_name)
|
@ -50,6 +50,7 @@ services:
|
||||
- BAIDU_SPEECH_API_KEY=YOUR_API_KEY
|
||||
- BAIDU_SPEECH_SECRET_KEY=YOUR_SECRET_KEY
|
||||
- BING_SPEECH_API_KEY=YOUR_API_KEY
|
||||
- HEWEATHER_API_KEY=YOUR_API_KEY
|
||||
restart: always
|
||||
networks:
|
||||
my-net:
|
||||
|
Loading…
Reference in New Issue
Block a user