async def book(bot, event: Message, keyword: str): """ 책 검색 책 제목으로 네이버 책 DB에서 검색합니다. `{PREFIX}책 소드 아트 온라인` (`소드 아트 온라인`으로 책 검색) """ url = 'https://openapi.naver.com/v1/search/book.json' params = { 'query': keyword, } headers = { 'X-Naver-Client-Id': bot.config.NAVER_CLIENT_ID, 'X-Naver-Client-Secret': bot.config.NAVER_CLIENT_SECRET, } async with aiohttp.ClientSession() as session: async with session.get(url, params=params, headers=headers) as resp: data = await resp.json(loads=json.loads) attachments: List[Attachment] = [] count = min(5, len(data['items'])) for i in range(count): book = data['items'][i] title = strip_tags(book['title']) attachments.append( Attachment( fallback='{} - {}'.format(title, book['link']), title=title, title_link=book['link'], thumb_url=book['image'], text='저자: {} / 출판사: {}{}'.format( strip_tags(book['author']), strip_tags(book['publisher']), ' / 정가: ₩{:,}'.format(Decimal(book['price'])) if book['price'] else '', ), )) if attachments: await bot.api.chat.postMessage( channel=event.channel, text=('키워드 *{}* {} 네이버 책 DB 검색 결과, 총 {:,}개의 결과가 나왔어요.' ' 그 중 상위 {}개를 보여드릴게요!').format( keyword, tossi.pick(keyword, '(으)로'), data['total'], count, ), attachments=attachments, as_user=True, thread_ts=event.ts, ) else: await bot.say(event.channel, '검색 결과가 없어요!')
async def memo_add(bot, event: Message, sess, keyword: str, text: str): """ 기억 레코드 생성 `{PREFIX}기억 키리토 귀엽다` (`키리토`라는 단어를 `귀엽다`라는 내용으로 저장) `{PREFIX}기억 "키리가야 카즈토" "키리토의 본명"` (`키리가야 카즈토`에 대한 정보를 저장) """ memo = Memo() memo.keyword = keyword memo.author = event.user.id memo.text = text memo.created_at = now() with sess.begin(): sess.add(memo) await bot.say( event.channel, '{}{} 기억 레코드를 생성했어요!'.format( format.code(keyword), tossi.pick(keyword, '(으)로'), ), )
async def aqi(bot, event: Message, address: str): """ AQI 지수 열람 Air Quality Index(AQI) 지수를 열람합니다. 주소를 입력하면 가장 가까운 계측기의 정보를 열람합니다. `{PREFIX}공기 부천` (경기도 부천시의 AQI 지수 열람) """ try: full_address, lat, lng = await get_geometric_info_by_address( address, bot.config.GOOGLE_API_KEY, ) except IndexError: await bot.say(event.channel, '해당 주소는 찾을 수 없어요!') return result = await get_aqi(lat, lng, bot.config.AQI_API_TOKEN) if result is None: await bot.say(event.channel, '현재 AQI 서버의 상태가 좋지 않아요! 나중에 다시 시도해주세요!') return time = datetime.datetime.fromtimestamp(result.time) time -= tzlocal.get_localzone().utcoffset(time) ftime = time.strftime('%Y년 %m월 %d일 %H시') j = tossi.pick(full_address, '를') text = (f'{ftime} 계측 자료에요. {full_address}{j} 기준으로 AQI에 정보를 요청했어요!\n\n' f'* 종합 AQI: {result.aqi} - {get_aqi_description(result.aqi)}\n') if result.pm25: text += f'* PM2.5: {result.pm25}\n' if result.pm10: text += f'* PM10: {result.pm10}\n' if result.o3: text += f'* 오존: {result.o3}\n' if result.no2: text += f'* 이산화 질소: {result.no2}\n' if result.so2: text += f'* 이산화 황: {result.so2}\n' if result.co: text += f'* 일산화 탄소: {result.co}\n' text = text.strip() await bot.say( event.channel, text, thread_ts=event.ts, )
async def aqi(bot, event: Message, address: str): """ AQI 지수 열람 Air Quality Index(AQI) 지수를 열람합니다. 주소를 입력하면 가장 가까운 계측기의 정보를 열람합니다. `{PREFIX}공기 부천` (경기도 부천시의 AQI 지수 열람) """ try: full_address, lat, lng = await get_geometric_info_by_address( address, bot.config.GOOGLE_API_KEY, ) except IndexError: await bot.say(event.channel, '해당 주소는 찾을 수 없어요!') return result = await get_aqi(lat, lng, bot.config.AQI_API_TOKEN) if result is None: await bot.say(event.channel, '현재 AQI 서버의 상태가 좋지 않아요! 나중에 다시 시도해주세요!') return time = datetime.datetime.fromtimestamp(result.time) time -= tzlocal.get_localzone().utcoffset(time) ftime = time.strftime('%Y년 %m월 %d일 %H시') j = tossi.pick(full_address, '를') text = (f'{result.name}의 {ftime} 계측 자료에요.' f' {full_address}{j} 기준으로 AQI에 정보를 요청했어요!\n\n' f'* 종합 AQI: {result.aqi} - {get_aqi_description(result.aqi)}\n') for key, name in LABELS.items(): if hasattr(result, key): f: Field = getattr(result, key) text += f'* {name}: {f.current} (최소 {f.min} / 최대 {f.max})\n' text = text.strip() await bot.say( event.channel, text, thread_ts=event.ts, )
async def memo_show(bot, event: Message, sess, keyword: str): """ 기억 레코드 출력 `{PREFIX}알려 키리토` (`키리토`에 관한 모든 기억 레코드를 출력) """ memos = sess.query(Memo).filter_by(keyword=keyword)\ .order_by(Memo.created_datetime).all() if memos: await bot.say(event.channel, f'`{keyword}`: ' + ' | '.join(x.text for x in memos)) else: await bot.say( event.channel, '`{}`{} 이름을 가진 기억 레코드가 없어요!'.format( keyword, tossi.pick(keyword, '(이)란'), ))
async def memo_add(bot, event: Message, sess: AsyncSession, keyword: str, text: str): """ 기억 레코드 생성 `{PREFIX}기억 키리토 귀엽다` (`키리토`라는 단어를 `귀엽다`라는 내용으로 저장) `{PREFIX}기억 "키리가야 카즈토" "키리토의 본명"` (`키리가야 카즈토`에 대한 정보를 저장) """ if len(keyword) > 20: await bot.say( event.channel, "기억하려는 키워드가 너무 길어요! 20자 이하의 키워드만 가능해요!", ) return if len(text) > 500: await bot.say( event.channel, "기억하려는 내용이 너무 길어요! 500자 이하의 내용만 가능해요!", ) return memo = Memo() memo.keyword = keyword memo.author = event.user memo.text = text memo.created_at = now() sess.add(memo) await sess.commit() await bot.say( event.channel, "{}{} 기억 레코드를 생성했어요!".format( format.code(keyword), tossi.pick(keyword, "(으)로"), ), )
async def memo_show(bot, event: Message, sess: AsyncSession, keyword: str): """ 기억 레코드 출력 `{PREFIX}알려 키리토` (`키리토`에 관한 모든 기억 레코드를 출력) """ memos = (await sess.scalars( select(Memo).where(Memo.keyword == keyword).order_by( Memo.created_at.asc()))).all() if memos: await bot.say( event.channel, f"{format.code(keyword)}: " + " | ".join(x.text for x in memos), ) else: await bot.say( event.channel, "{}{} 이름을 가진 기억 레코드가 없어요!".format( format.code(keyword), tossi.pick(keyword, "(이)란"), ), )
async def memo_show(bot, event: Message, sess, keyword: str): """ 기억 레코드 출력 `{PREFIX}알려 키리토` (`키리토`에 관한 모든 기억 레코드를 출력) """ memos = (sess.query(Memo).filter_by(keyword=keyword).order_by( Memo.created_at.asc()).all()) if memos: await bot.say( event.channel, f'{format.code(keyword)}: ' + ' | '.join(x.text for x in memos), ) else: await bot.say( event.channel, '{}{} 이름을 가진 기억 레코드가 없어요!'.format( format.code(keyword), tossi.pick(keyword, '(이)란'), ), )
def test_pick(): assert tossi.pick(u'나오', u'을') == u'를' assert tossi.pick(u'키홀', u'를') == u'을' assert tossi.pick(u'남', u'면서') == u'이면서' assert tossi.pick(u'Tossi', u'을') == u'을(를)' assert tossi.pick(u'Tossi', u'을', tolerance_style=u'을/를') == u'을/를'
async def book(bot, event: Message, keyword: str): """ 책 검색 책 제목으로 네이버 책 DB에서 검색합니다. `{PREFIX}책 소드 아트 온라인` (`소드 아트 온라인`으로 책 검색) """ url = "https://openapi.naver.com/v1/search/book.json" params = { "query": keyword, } headers = { "X-Naver-Client-Id": bot.config.NAVER_CLIENT_ID, "X-Naver-Client-Secret": bot.config.NAVER_CLIENT_SECRET, } async with aiohttp.ClientSession() as session: async with session.get(url, params=params, headers=headers) as resp: data = await resp.json(loads=json.loads) attachments: list[Attachment] = [] count = min(5, len(data["items"])) for i in range(count): book = data["items"][i] title = strip_tags(book["title"]) attachments.append( Attachment( fallback="{} - {}".format(title, book["link"]), title=title, title_link=book["link"], thumb_url=book["image"], text="저자: {} / 출판사: {}{}".format( strip_tags(book["author"]), strip_tags(book["publisher"]), " / 정가: ₩{:,}".format(Decimal(book["price"])) if book["price"] else "", ), ) ) if attachments: await bot.api.chat.postMessage( channel=event.channel, text=( "키워드 *{}* {} 네이버 책 DB 검색 결과, 총 {:,}개의 결과가 나왔어요." " 그 중 상위 {}개를 보여드릴게요!" ).format( keyword, tossi.pick(keyword, "(으)로"), data["total"], count, ), attachments=attachments, as_user=True, thread_ts=event.ts, ) else: await bot.say(event.channel, "검색 결과가 없어요!")