async def _meal(self, ctx, schoolname: str = None, date: str = neispy.now()): """ 설명:해당학교의 급식정보를 알려줍니다. 날짜가 주어지지 않았을경우 현재 날짜로 가져옵니다. 인자값: 학교명(미설정시 필수) 날짜(선택) 예시: ?급식 인천기계공업고등학교 ?급식 인천기계공업고등학교 20200810 """ if schoolname and schoolname.isdigit(): schoolname, date = None, schoolname if schoolname: School = await self.Bot.search_school(ctx, schoolname) if not School: return Data, AE, SE = None, School.ATPT_OFCDC_SC_CODE, School.SD_SCHUL_CODE else: Data = await User.get_or_none(id=ctx.author.id) if not Data: return await ctx.send( embed=discord.Embed(title="학교명을 입력 해주세요.", colur=discord.Colour.red()), mobile=is_mobile(ctx.author), ) AE, SE = Data.neis_ae, Data.neis_se try: meal = await self.Bot.neis.mealServiceDietInfo(AE, SE, MLSV_YMD=date) except neispy.DataNotFound: return await ctx.send( datetime.strptime(date, "%Y%m%d").strftime("%m월 %d일") + "의 급식 정보를 찾을 수 없습니다.", mobile=is_mobile(ctx.author), ) else: meal = meal[0] embed = discord.Embed( title= f"{meal.SCHUL_NM if not Data or Data.public else '`학교 비공개`'}의 급식입니다.", colour=0x2E3136, ).add_field( name=datetime.strptime(meal.MLSV_YMD, "%Y%m%d").strftime("%Y년 %m월 %d일"), value=meal.DDISH_NM.replace("<br/>", "\n"), ) message = await ctx.send(embed=embed, mobile=is_mobile(ctx.author)) embed.set_image(url=await self.__get_meal_image(meal.DDISH_NM)) await message.edit(embed=embed, mobile=is_mobile(ctx.author))
async def _schedule(self, ctx, schoolname: str = None, date: str = neispy.now()): """ 설명:해당학교의 학사정보를 알려줍니다. 날짜가 주어지지 않았을경우 현재 날짜로 가져옵니다. 인자값: 학교명(미설정시 필수) 날짜(선택) 예시: ?학사일정 인천기계공업고등학교 ?학사일정 인천기계공업고등학교 20200808 """ if schoolname and schoolname.isdigit(): schoolname, date = None, schoolname if schoolname: School = await self.Bot.search_school(ctx, schoolname) if not School: return Data, AE, SE = None, School.ATPT_OFCDC_SC_CODE, School.SD_SCHUL_CODE else: Data = await User.get_or_none(id=ctx.author.id) if not Data: return await ctx.send( embed=discord.Embed(title="학교명을 입력해주세요.", colur=discord.Colour.red()), mobile=is_mobile(ctx.author), ) AE, SE = Data.neis_ae, Data.neis_se try: schedule = await self.Bot.neis.SchoolSchedule(AE, SE, AA_YMD=date) except neispy.DataNotFound: return await ctx.send( datetime.strptime(date, "%Y%m%d").strftime("%m월 %d일") + "의 학사일정을 찾을 수 없습니다.", mobile=is_mobile(ctx.author), ) else: schedule = schedule[0] await ctx.send( embed=discord.Embed( title= f"{schedule.SCHUL_NM if not Data or Data.public else '`학교 비공개`'}의 학사일정입니다", description=datetime.strptime( schedule.AA_YMD, "%Y%m%d").strftime("%Y년 %m월 %d일"), colour=0x2E3136, ).add_field( name=f"**{schedule.EVENT_NM}**", value= f"{schedule.EVENT_CNTNT if schedule.EVENT_CNTNT else '해당 학사일정의 내용이 없습니다.'}", ), mobile=is_mobile(ctx.author), )
async def on_command_error(self, ctx, error): if isinstance(error, commands.CommandNotFound): return elif isinstance(error, commands.MissingRequiredArgument): await ctx.send( "⚠️ 명령에 누락된 항목이 있습니다. `?도움말` 명령어를 통해 정확한 사용법을 보실 수 있습니다.", delete_after=5, ) elif isinstance(error, commands.BadArgument): await ctx.send( "⚠️ 잘못된 명령입니다. `?도움말` 명령어를 통해 정확한 사용법을 보실 수 있습니다.", delete_after=5, ) elif isinstance(error, commands.NotOwner): await ctx.send("⚠️ 관리자만 사용가능한 명령어입니다.", delete_after=5) else: trace_uuid = str(uuid.uuid4()) await ctx.send( embed=discord.Embed( title="⚠️ 알 수 없는 오류가 발생했습니다.", description= f"다음 정보를 개발자에게 알려주시면 문제해결에 도움이됩니다.\n**UUID**: ``{trace_uuid}``\n\n베타테스트 기간입니다, 발생 경위를 <#751768265088565279>에 보내주세요.", colour=discord.Color.red(), ), mobile=is_mobile(ctx.author), ) trace_embed = discord.Embed( title= f"Unexpected Error in schoolbot\n**UUID**: ``{trace_uuid}``", description=f"**Version**: ``{self.bot.__version__}``\n" f"**User**: ``{ctx.author}`` (``{ctx.author.id}``)\n" f"**Guild**: ``{ctx.author.guild}`` (``{ctx.author.guild.id}``)\n" f"**Channel**: ``{ctx.channel}`` (``{ctx.channel.id}``)\n" f"**Command**: ``{ctx.command}``\n" f"**Bot Permission**: ``{ctx.guild.me.guild_permissions.value}``", timestamp=datetime.utcnow(), ) if not error.__cause__: trace_embed.add_field( name="Traceback:", value= f"```py\n{''.join(traceback.format_exception(type(error), error, error.__traceback__, limit=3))}\n```", ) else: trace_embed.add_field( name="Traceback:", value= f"```py\n{''.join(traceback.format_exception(type(error.__cause__), error.__cause__, error.__cause__.__traceback__, limit=3))}\n```", ) channel = await self.bot.fetch_channel(os.environ["channel_id"]) await channel.send(embed=trace_embed, mobile=is_mobile(ctx.author))
async def select_list(self, ctx, Data: list, string_list: list = None, title: str = "여러개의 검색 결과입니다."): if not string_list: string_list = [ f"{index}. {Value}" for index, Value in enumerate(Data, 1) ] if not isinstance(Data, list): Data = list(Data) if len(Data) == 1: return Data[0] Data = Data[:10] message = await ctx.send( embed=discord.Embed( title=title, description="\n".join(string_list), colur=discord.Colour.blurple(), ), mobile=is_mobile(ctx.author), ) try: response = await self.Bot.wait_for( "message", check=lambda m: m.author == ctx.author and m.channel == message .channel, timeout=30.0, ) except asyncio.TimeoutError: await message.edit(embed=discord.Embed( title="시간 초과 입니다. 처음부터 다시 시도 해주세요.", colur=discord.Colour.red(), mobile=is_mobile(ctx.author), )) return if not response.content.isdigit() or 1 > int( response.content) > len(Data): await message.edit(embed=discord.Embed( title="잘못된 값을 받았습니다. 확인 후 다시 시도 해주세요.", colur=discord.Colour.red(), mobile=is_mobile(ctx.author), )) return await message.delete() return Data[int(response.content) - 1]
def _add_payment(self, model, recipient, message, amount): email = recipient if is_email(recipient) else None mobile = recipient if is_mobile(recipient) else None address = recipient if is_address(recipient) else None amount = int(amount * 100) payment = Payment(model, mobile, email, address, message, amount) self.session.add(payment)
def login(): # set mobilecookie to reduce is_mobile check-time response.set_cookie("mobile", str(is_mobile())) if not PYLOAD and SETUP: redirect("/setup") else: return render_to_response("login.html", proc=[pre_processor])
def validate_recipient(recipient): if not recipient or \ (not is_email(recipient) and not is_mobile(recipient) and not is_address(recipient)): return False ##TODO: direct wallet address not yet implemented if is_address(recipient): return False return True
def on_keyboard(self, window, keycode1, keycode2, text, modifiers): undo = keycode1 in [27, 1001] if is_mobile() else ( keycode1 == 122 and 'ctrl' in modifiers) if undo and self.engine.can_undo(): self.confirm('Take back last move', self.undo_move) return True elif keycode1 == 27: return True # don't close on Escape
async def _search(self, ctx, schoolname: str = None): """ 설명:학교 설정에 필요한 학교 정보를 검색합니다. 인자값: 학교명(필수) 예시: ?검색 인천기계공업고등학교 """ if not schoolname: return await ctx.send( embed=discord.Embed(title="학교명을 입력해 주세요.", colur=discord.Colour.red()), mobile=is_mobile(ctx.author), ) School = await self.Bot.search_school(ctx, schoolname) if not School: return AE, SE, SCHOOL_TYPE = ( School.ATPT_OFCDC_SC_CODE, School.SD_SCHUL_CODE, SCHUL_KND_SC_NM[School.SCHUL_KND_SC_NM], ) await ctx.send( embed=discord.Embed(title="검색 정보") .add_field(name=School.ORG_RDNMA, value=School.SCHUL_NM, inline=False) .add_field(name="학교 ID", value=f"{AE}{SE}") .add_field(name="유형", value=School.SCHUL_KND_SC_NM) .add_field( name="설립일", value=datetime.strptime(School.FOND_YMD, "%Y%m%d").strftime("%Y-%m-%d"), ) .add_field(name="남녀 구분", value=School.COEDU_SC_NM) .add_field(name="우편번호", value=School.ORG_RDNZC) .add_field( name="전화번호 / 팩스번호", value=f"{School.ORG_TELNO} / {School.ORG_FAXNO}" ) .add_field(name="홈페이지", value=School.HMPG_ADRES) .add_field(name="설립 유형", value=School.FOND_SC_NM) .add_field( name="검색된 정보가 일치한가요?", value=f"`{self.Bot.command_prefix}설정 학교 {AE}|{SE}|{SCHOOL_TYPE} <학년> <반>`를 입력해서 학교를 설정할 수 있습니다!", ), mobile=is_mobile(ctx.author), )
async def pagination(self, ctx, callback: Callable, limit: int): position = 0 message = await ctx.send(embed=callback(position), mobile=is_mobile(ctx.author)) async def _add_emojis(): try: for emoji in ["◀", "⏹", "▶"]: await message.add_reaction(emoji) except: pass self.Bot.loop.create_task(_add_emojis()) while not self.Bot.is_closed(): try: reaction, user = await self.Bot.wait_for( "reaction_add", check=lambda reaction, user: user == ctx.author and reaction.message.id == message.id and reaction.emoji in ["◀", "⏹", "▶"], timeout=30, ) except asyncio.TimeoutError: await message.clear_reactions() break if reaction.emoji == "◀" and position > 0: position -= 1 elif reaction.emoji == "⏹": try: await message.clear_reactions() except: pass break elif reaction.emoji == "▶" and position < limit: position += 1 await message.edit(embed=callback(position), mobile=is_mobile(ctx.author)) await message.remove_reaction(reaction.emoji, user)
def _reward_create(user, reason, category, recipient, amount, message): proposal = Proposal(user, reason) proposal.categories.append(category) proposal.authorize(user) db.session.add(proposal) email = recipient if utils.is_email(recipient) else None mobile = recipient if utils.is_mobile(recipient) else None address = recipient if utils.is_address(recipient) else None payment = Payment(proposal, mobile, email, address, message, amount) db.session.add(payment) return proposal, payment
def build(self): if is_mobile(): Window.maximize() else: Window.size = (600, 720) Window.bind(on_request_close=self.on_quit) Window.bind(on_keyboard=self.on_keyboard) root = Root() for id, wid in root.ids.items(): cls = str(wid.__class__).split('.')[-1].split('\'')[0].lower() setattr(self, id if id == cls else id + '_' + cls, wid) self.board.bind(on_move=self.on_move) return root
def get(self): if is_mobile(self.request): mkey = 'html/mobile' else: mkey = 'html/index' html = memcache.get(mkey) if html is not None: return self.response.out.write(html) rdic = {} rdic['articles'] = dbs.Article.getten() rdic['links'] = dbs.Melody.get_all('link') rdic['navs'] = get_navs() path = get_path(self.request, 'index.html') html = render(path, rdic) memcache.set(mkey, html, 300) self.response.out.write(html)
async def _help(self, ctx): embed = discord.Embed( title="도움말", description=f"접두사: ``{self.Bot.command_prefix}``" ) for Command in [ i for i in self.Bot.commands if i.help if "jishaku" not in i.name ]: embed.add_field( name=Command.name, value=Command.help, inline=False, ) embed.add_field( name="유용한 링크", value="[이용약관](https://callisto.team/tos)\n[개인정보취급방침](https://callisto.team/privacy)", inline=False, ) await ctx.send(embed=embed, mobile=is_mobile(ctx.author))
def toggle_mobile(): response.set_cookie("mobile", str(not is_mobile())) return redirect("/")
async def _time_table( self, ctx, a: str = None, b: str = None, c: str = None, d: str = None, e: str = None, f: str = neispy.now(), ): """ 설명:해당학교의 시간표를 알려줍니다. 날짜가 주어지지 않았을경우 현재 날짜로 가져옵니다. 현재 고등학교는 가져올수 없습니다. 인자값: 학교명(미설정시 필수) 학년(미설정시 필수) 반(미설정시 필수) 날짜(선택) 예시: ?시간표 구월중학교 2 1 ?시간표 구월중학교 2 1 20200810 """ schoolname = grade = class_ = AFLCO = MAJOR = date = None for Data in [Item for Item in [a, b, c, d, e, f] if Item]: if not schoolname and re.fullmatch("[가-힣]+", Data): schoolname = Data elif not grade and re.fullmatch("[1-6]{1}", Data): grade = Data elif not class_ and re.fullmatch("[0-9]{1,2}", Data): class_ = Data elif not AFLCO and re.fullmatch("[가-힣]+", Data): AFLCO = Data elif not MAJOR and re.fullmatch("[가-힣]+", Data): MAJOR = Data elif not date and re.fullmatch( "[0-9]{8}", Data, ): date = Data if schoolname: School = await self.Bot.search_school(ctx, schoolname) if not School: return Data, AE, SE, SN = ( None, School.ATPT_OFCDC_SC_CODE, School.SD_SCHUL_CODE, SCHUL_KND_SC_NM[School.SCHUL_KND_SC_NM], ) if not (grade and class_): return await ctx.send("학년과 반을 입력해주세요", mobile=is_mobile(ctx.author)) if SN == "his" and not (AFLCO and MAJOR): return await ctx.send("계열과 학과를 입력해주세요", mobile=is_mobile(ctx.author)) else: Data = await User.get_or_none(id=ctx.author.id) if not Data: return await ctx.send( embed=discord.Embed(title="학교명을 입력 해주세요.", colur=discord.Colour.red()), mobile=is_mobile(ctx.author), ) AE, SE, SN, AFLCO, MAJOR = ( Data.neis_ae, Data.neis_se, Data.school_type, Data.aflco, Data.major, ) if not grade: grade = Data.grade if not class_: class_ = Data.class_ try: timetable = await self.Bot.neis.timeTable( SN, AE, SE, ALL_TI_YMD=date, TI_FROM_YMD=date, TI_TO_YMD=date, GRADE=grade, ORD_SC_NM=AFLCO, DDDEP_NM=MAJOR, ) except neispy.DataNotFound: return await ctx.send( datetime.strptime(date, "%Y%m%d").strftime("%m월 %d일") + "의 시간표 정보를 찾을 수 없습니다.", mobile=is_mobile(ctx.author), ) timetable = [ time for time in timetable if int(time.CLASS_NM) == int(class_) ] await ctx.send( embed=discord.Embed( title= f"{timetable[0].SCHUL_NM if not Data or Data.public else '`학교 비공개`'}의 시간표입니다.", colour=0x2E3136, ).add_field( name=datetime.strptime(timetable[0].ALL_TI_YMD, "%Y%m%d").strftime("%Y년 %m월 %d일"), value="\n".join([ f"{index}교시 {value.ITRT_CNTNT}" for index, value in enumerate(timetable, 1) ]), ), mobile=is_mobile(ctx.author), )
def get_path(request, name): if is_mobile(request): path = os.path.join(config.ROOT, 'tpl','mobile' , name) return path path = os.path.join(config.ROOT, 'tpl', config.THEME, name) return path
def get_path(request , name): if is_mobile(request): path = os.path.join(ROOT, 'god','mobile' , name) return path path = os.path.join(ROOT, 'god', 'tpl', name) return path
async def _setting(self, ctx, key: str, *, value: str): """ 설명:학교 정보와 공개 여부를 설정합니다. 인자값: 키(필수) 값(필수) 예시: ?설정 학교 E10|7310100 1 1 ?설정 공개 아니요 """ if key == "학교": # F10|7401249|mis <학년> <반> Value = re.match( r"(B10|C10|D10|E10|F10|G10|H10|I10|J10|K10|M10|N10|P10|Q10|R10|S10|T10|V10)\|([0-9]{7})\|(els|mis|his|sps)\s([0-9]{1})\s([0-9]{1,2})", value, flags=re.I, ) if not Value: return await ctx.send( embed=discord.Embed(title="올바른 정보를 입력해주세요"), mobile=is_mobile(ctx.author), ) Data = (await User.get_or_create(id=ctx.author.id))[0] Data.neis_ae = Value.group(1) Data.neis_se = Value.group(2) Data.school_type = Value.group(3) Data.grade = int(Value.group(4)) Data.class_ = int(Value.group(5)) Data.iamschool = "0" if Data.school_type == "his": try: Classes = await self.Bot.neis.classInfo( ATPT_OFCDC_SC_CODE=Data.neis_ae, SD_SCHUL_CODE=Data.neis_se, AY=datetime.now().year, GRADE=Data.grade, ) except neispy.DataNotFound: return await ctx.send( "해당 학교의 정보를 찾을 수 없습니다. 잠시 후 다시시도해주세요.") AflcoList = {Class.ORD_SC_NM for Class in Classes} Data.aflco = await self.Bot.select_list(ctx, AflcoList, title="계열을 선택해주세요.") if not Data.aflco: return MajorList = { Class.DDDEP_NM for Class in Classes if (Class.CLASS_NM.isdigit() and int(Class.CLASS_NM) == Data.class_) and Class.ORD_SC_NM == Data.aflco } Data.major = await self.Bot.select_list(ctx, MajorList, title="학과를 선택해주세요.") if not Data.major: return await Data.save() return await ctx.send( embed=discord.Embed(title="학교 정보가 설정되었습니다."), mobile=is_mobile(ctx.author), ) if key == "공개": # 공개|비공개 Data = await User.get_or_none(id=ctx.author.id) if not Data: return await ctx.send( embed=discord.Embed(title="학교를 먼저 설정해주세요!"), mobile=is_mobile(ctx.author), ) if value in POSITIVE: Data.public = True elif value in NEGATIVE: Data.public = False else: return await ctx.send( embed=discord.Embed(title="올바른 정보를 입력해주세요"), mobile=is_mobile(ctx.author), ) await Data.save() return await ctx.send( embed=discord.Embed(title="학교 공개 여부가 설정되었습니다."), mobile=is_mobile(ctx.author), ) else: return await ctx.send( embed=discord.Embed(title="설정할 수 없는 항목입니다."), mobile=is_mobile(ctx.author), )
async def _article(self, ctx, schoolname: str = None): """ 설명:해당학교의 아이엠스쿨 게시물을 가져옵니다. 인자값: 학교명(필수) 예시: ?게시물 인천기계공업고등학교 """ if not schoolname: user_data = await User.get_or_none(id=ctx.author.id) if not user_data: return await ctx.send( embed=discord.Embed(title="학교명을 입력해주세요.", colur=discord.Colour.red()), mobile=is_mobile(ctx.author), ) if user_data.iamschool == "0": try: School = await self.Bot.neis.schoolInfo( ATPT_OFCDC_SC_CODE=user_data.neis_ae, SD_SCHUL_CODE=user_data.neis_se, ) except neispy.DataNotFound: return await ctx.send(embed=discord.Embed( title="학교 정보가 없습니다. 확인 후 다시 시도해주세요.", colur=discord.Colour.red(), )) schoolname, school_id = School[0].SCHUL_NM, None else: school_id = user_data.iamschool else: user_data = school_id = None if not school_id: try: Data = await self.client.search_school(schoolname) except HTTPException: return await ctx.send( embed=discord.Embed( title="일시적인 오류입니다, 잠시 후 다시시도해주세요.", colour=discord.Colour.red(), ), mobile=is_mobile(ctx.author), ) if not Data: return await ctx.send( embed=discord.Embed( title="아이엠스쿨에 등록되지 않았습니다. 확인하신후 다시 요청하세요", description= " [아이엠스쿨 바로가기](https://school.iamservice.net/) ", colour=discord.Colour.red(), ), mobile=is_mobile(ctx.author), ) if len(Data) == 1: Data = Data[0] else: school_list = [ f"{index}. {school.name}" for index, school in enumerate(Data, 1) ] message = await ctx.send( embed=discord.Embed( title="여러개의 검색 결과입니다.", description="\n".join(school_list), colur=discord.Colour.blurple(), ), mobile=is_mobile(ctx.author), ) try: response = await self.Bot.wait_for( "message", check=lambda m: m.author == ctx.author and m.channel == message.channel, timeout=30.0, ) except asyncio.TimeoutError: return await message.edit( embed=discord.Embed( title="명령어 시간 초과입니다. 처음부터 다시 시도해주세요.", colur=discord.Colour.red(), ), mobile=is_mobile(ctx.author), ) if not response.content.isdigit(): return await message.edit( embed=discord.Embed( title="정수만 입력 가능합니다. 확인 후 다시 시도 해주세요.", colur=discord.Colour.red(), ), mobile=is_mobile(ctx.author), ) Data = Data[int(response.content) - 1] await message.delete() school_id = Data.id if user_data: user_data.iamschool = school_id await user_data.save() try: articles = await self.client.fetch_recent_article(school_id) except HTTPException: return await ctx.send( embed=discord.Embed( title="일시적인 오류입니다, 잠시 후 다시시도해주세요.", colour=discord.Colour.red(), ), mobile=is_mobile(ctx.author), ) if not articles: return await ctx.send( embed=discord.Embed( title="아이엠스쿨에 게시된 게시물이 없습니다.", description=" [아이엠스쿨 바로가기](https://school.iamservice.net/)", colour=discord.Colour.red(), ), mobile=is_mobile(ctx.author), ) def callback(position): embed = discord.Embed( title=articles[position].title, description=articles[position].content, timestamp=datetime.strptime(articles[position].date, "%Y.%m.%d"), url=articles[position].link, colour=0x2E3136, ).set_footer( text= f"#{articles[position].group.name} • {articles[position].author}" ) if articles[position].images: embed.set_image(url=articles[position].images[0]) if not user_data or user_data.public: embed.set_author( name=articles[position].organization_name, url= f"https://school.iamservice.net/organization/{articles[position].organization_id}", icon_url=articles[position].organization_logo, ) return embed await self.Bot.pagination(ctx, callback, limit=len(articles))