Best JavaScript code snippet using best
app.py
Source:app.py
1import asyncio2from base64 import urlsafe_b64decode, urlsafe_b64encode3import datetime4import json5import uuid6import aiohttp7import discord8import secrets as _secrets9from discord.ext import commands10from fastapi.responses import HTMLResponse, ORJSONResponse, RedirectResponse11from fastapi.security.api_key import APIKeyHeader12from fastapi import Depends, FastAPI, Request, WebSocket, WebSocketDisconnect13from fastapi.routing import Mount14import orjson15from piccolo.engine import engine_finder16from piccolo_admin.endpoints import create_admin17import piccolo18import pydantic19from . import tables20import inspect21_tables = []22tables_dict = vars(tables)23for obj in tables_dict.values():24 if obj == tables.Table:25 continue26 if inspect.isclass(obj) and isinstance(obj, piccolo.table.TableMetaclass):27 _tables.append(obj)28app = FastAPI(29 routes=[30 Mount(31 "/admin/",32 create_admin(33 tables=_tables,34 site_name="BRC Admin",35 production=True,36 # Required when running under HTTPS:37 allowed_hosts=['catnip.metrobots.xyz']38 ),39 ),40 ],41)42with open("site.html") as site:43 site_html = site.read()44bot = commands.Bot(intents=discord.Intents.all(), command_prefix="%")45with open("secrets.json") as f:46 secrets = json.load(f)47 secrets["gid"] = int(secrets["gid"])48 secrets["reviewer"] = int(secrets["reviewer"])49 secrets["queue_channel"] = int(secrets["queue_channel"])50@app.on_event("startup")51async def open_database_connection_pool():52 engine = engine_finder()53 asyncio.create_task(bot.start(secrets["token"]))54 await bot.load_extension("jishaku")55 await engine.start_connnection_pool()56@app.on_event("shutdown")57async def close_database_connection_pool():58 engine = engine_finder()59 await engine.close_connnection_pool()60@app.get("/list/{id}")61async def get_list(id: uuid.UUID):62 return await tables.BotList.select(tables.BotList.id, tables.BotList.name, tables.BotList.description, tables.BotList.domain, tables.BotList.state, tables.BotList.icon).where(tables.BotList.id == id).first()63@app.get("/lists")64async def get_all_lists():65 return await tables.BotList.select(tables.BotList.id, tables.BotList.name, tables.BotList.description, tables.BotList.domain, tables.BotList.state, tables.BotList.icon).order_by(tables.BotList.id, ascending=True)66class BotPost(pydantic.BaseModel):67 bot_id: str68 username: str69 banner: str | None = None70 description: str 71 long_description: str72 website: str | None = None73 invite: str | None = None74 owner: str75 extra_owners: list[str]76 support: str | None = None77 donate: str | None = None78 library: str | None = None79 nsfw: bool | None = False80 prefix: str | None = None81 tags: list[str] | None = None82 review_note: str | None = None83 cross_add: bool | None = True84class Bot(BotPost):85 state: tables.State86 list_source: uuid.UUID87 added_at: datetime.datetime88 reviewer: str | None = None89 invite_link: str | None = None90class ListUpdate(pydantic.BaseModel):91 name: str | None = None92 description: str | None = None93 domain: str | None = None94 claim_bot_api: str | None = None95 unclaim_bot_api: str | None = None96 approve_bot_api: str | None = None97 deny_bot_api: str | None = None98 reset_secret_key: bool = False99 icon: str | None = None100auth_header = APIKeyHeader(name='Authorization')101@app.patch("/lists/{list_id}")102async def update_list(list_id: uuid.UUID, update: ListUpdate, auth: str = Depends(auth_header)):103 if (auth := await _auth(list_id, auth)):104 return auth 105 106 has_updated = []107 if update.name:108 await tables.BotList.update(name=update.name).where(tables.BotList.id == list_id)109 has_updated.append("name")110 if update.description:111 await tables.BotList.update(name=update.name).where(tables.BotList.id == list_id)112 has_updated.append("description")113 if update.icon:114 if update.icon.startswith("https://"):115 await tables.BotList.update(icon=update.icon).where(tables.BotList.id == list_id)116 has_updated.append("icon")117 if update.claim_bot_api:118 await tables.BotList.update(claim_bot_api=update.claim_bot_api).where(tables.BotList.id == list_id)119 has_updated.append("claim_bot_api")120 if update.unclaim_bot_api:121 await tables.BotList.update(unclaim_bot_api=update.unclaim_bot_api).where(tables.BotList.id == list_id)122 has_updated.append("unclaim_bot_api")123 if update.approve_bot_api:124 await tables.BotList.update(approve_bot_api=update.approve_bot_api).where(tables.BotList.id == list_id)125 has_updated.append("approve_bot_api")126 if update.deny_bot_api:127 await tables.BotList.update(deny_bot_api=update.deny_bot_api).where(tables.BotList.id == list_id)128 has_updated.append("deny_bot_api")129 if update.domain:130 # Remove trailing /131 if update.domain.endswith("/"):132 update.domain = update.domain[:-1]133 await tables.BotList.update(domain=update.domain).where(tables.BotList.id == list_id)134 has_updated.append("domain")135 136 if has_updated and update.reset_secret_key:137 return ORJSONResponse({"error": "Cannot reset secret key while updating other fields"}, status_code=400)138 elif update.reset_secret_key:139 key = _secrets.token_urlsafe()140 await tables.BotList.update(secret_key=key).where(tables.BotList.id == list_id)141 return {"secret_key": key}142 return {"has_updated": has_updated}143@app.get("/bots/{id}", response_model=Bot)144async def get_bot(id: int) -> Bot:145 return await tables.BotQueue.select().where(tables.BotQueue.bot_id == id).first()146@app.get("/bots", response_model=list[Bot])147async def get_bots() -> list[Bot]:148 return await tables.BotQueue.select().order_by(tables.BotQueue.bot_id, ascending=True)149@app.get("/team")150async def our_team():151 guild = bot.get_guild(int(secrets["gid"]))152 if not guild:153 return {"detail": "Guild not found"}154 155 team = []156 for member in guild.members:157 if member.id in []:158 continue159 list_roles = []160 is_list_owner = False161 sudo = False162 is_reviewer = False163 for role in member.roles:164 if "list" in role.name.lower() and not role.name.lower().startswith("list"):165 list_roles.append(role.name)166 if role.id == int(secrets["list_owner"]):167 is_list_owner = True168 elif role.id == int(secrets["sudo"]):169 sudo = True170 elif role.id == int(secrets["reviewer"]):171 is_reviewer = True172 if is_reviewer:173 team.append({174 "username": member.name, 175 "id": str(member.id), 176 "avatar": member.avatar.url,177 "is_list_owner": is_list_owner,178 "sudo": sudo,179 "roles": list_roles180 })181 return team182class Action(pydantic.BaseModel):183 id: int184 bot_id: str185 action: tables.Action186 reason: str187 reviewer: str 188 action_time: datetime.datetime189 list_source: uuid.UUID190@app.get("/actions", response_model=list[Action])191async def get_actions(offset: int = 0, limit: int = 50) -> list[Action]:192 """193Returns a list of review action (such as claim bot, unclaim bot, approve bot and deny bot etc.)194``list_source`` will not be present in all cases.195**This is purely to allow Metro Review lists to debug their code**196Paginated using ``limit`` (how many rows to return at maximum) and ``offset`` (how many rows to skip). Maximum limit is 200197 """198 if limit > 200:199 return []200 return await tables.BotAction.select().limit(limit).offset(offset).order_by(tables.BotAction.action_time, ascending=False)201 202good_states = (tables.ListState.PENDING_API_SUPPORT, tables.ListState.SUPPORTED)203async def _auth(list_id: uuid.UUID, key: str) -> ORJSONResponse | None:204 list = await tables.BotList.select(tables.BotList.secret_key, tables.BotList.state).where(tables.BotList.id == list_id).first()205 if not list:206 return ORJSONResponse({"error": "List not found"}, status_code=404)207 if key != list["secret_key"]:208 return ORJSONResponse({"error": "Invalid secret key"}, status_code=401)209 210 if list["state"] not in good_states:211 return ORJSONResponse({"error": "List blacklisted, defunct or in an unknown state"}, status_code=401)212emotes = {213 "id": "<:idemote:912034927443320862>",214 "bot": "<:bot:970349895829561420>",215 "crown": "<:owner:912356178833596497>",216 "invite": "<:plus:912363980490702918>",217 "note": "<:activity:912031377422172160>" 218}219@app.post("/bots")220async def post_bots(request: Request, _bot: BotPost, list_id: uuid.UUID, auth: str = Depends(auth_header)):221 """222All optional fields are actually *optional* and does not need to be posted223``extra_owners`` should be a empty list if you do not support it224 """225 if (auth := await _auth(list_id, auth)):226 return auth 227 228 rem = []229 230 try:231 bot_id = int(_bot.bot_id)232 owner = int(_bot.owner)233 try:234 extra_owners = [int(v) for v in _bot.extra_owners]235 except:236 extra_owners = []237 rem.append("extra_owners")238 except:239 return ORJSONResponse({"error": "Invalid bot fields"}, status_code=400)240 241 if owner in extra_owners:242 flag = True243 while flag:244 try:245 extra_owners.remove(owner)246 except:247 flag = False248 extra_owners = list(set(extra_owners))249 if _bot.banner:250 if not _bot.banner.startswith("https://"):251 _bot.banner = bot.banner.replace("http://", "https://")252 if not _bot.banner.startswith("https://"):253 # We tried working around it, now we just remove the bad banner254 _bot.banner = None255 rem.append("banner")256 if _bot.website:257 if not _bot.website.startswith("https://"):258 _bot.website = _bot.website.replace("http://", "https://")259 if not _bot.website.startswith("https://"):260 # We tried working around it, now we just remove the bad website261 _bot.website = None262 rem.append("website")263 264 if _bot.support:265 if not _bot.support.startswith("https://"):266 _bot.support = _bot.support.replace("http://", "https://")267 if not _bot.support.startswith("https://"):268 # We tried working around it, now we just remove the bad support269 _bot.support = None270 rem.append("support")271 272 # Ensure add bot across lists *works*273 if _bot.tags:274 _bot.tags = [tag.lower() for tag in _bot.tags]275 if "utility" not in _bot.tags:276 _bot.tags.append("utility")277 else:278 _bot.tags = ["utility"]279 curr_bot = await tables.BotQueue.select(tables.BotQueue.bot_id).where(tables.BotQueue.bot_id == bot_id)280 if len(curr_bot) > 0:281 print("Bot already exists")282 return ORJSONResponse({"error": "Bot already in queue"}, status_code=409)283 if _bot.invite and not _bot.invite.startswith("https://"):284 # Just remove bad invite285 _bot.invite = None286 rem.append("invite")287 await tables.BotQueue.insert(288 tables.BotQueue(289 bot_id=bot_id, 290 username=_bot.username, 291 banner=_bot.banner,292 list_source=list_id,293 description=_bot.description,294 long_description=_bot.long_description,295 website=_bot.website,296 invite=_bot.invite,297 owner=owner,298 support=_bot.support,299 donate=_bot.donate,300 library=_bot.library,301 nsfw=_bot.nsfw,302 prefix=_bot.prefix,303 tags=_bot.tags,304 review_note=_bot.review_note,305 extra_owners=extra_owners,306 cross_add=_bot.cross_add,307 state=tables.State.PENDING308 )309 )310 if not _bot.invite:311 invite = f"https://discordapp.com/oauth2/authorize?client_id={bot_id}&scope=bot%20applications.commands&permissions=0"312 else:313 invite = _bot.invite314 # TODO: Add bot add propogation in final scope plans if this is successful315 embed = discord.Embed(url=f"https://metrobots.xyz/bots/{bot_id}", title="Bot Added To Queue", description=f"{emotes['id']} {bot_id}\n{emotes['bot']} {_bot.username}\n{emotes['crown']} {_bot.owner} (<@{_bot.owner}>)\n{emotes['invite']} [Invite]({invite})\n{emotes['note']} {_bot.review_note or 'No review notes for this bot'}", color=discord.Color.green())316 c = bot.get_channel(secrets["queue_channel"])317 await c.send(f"<@&{secrets['test_ping_role'] or secrets['reviewer']}>", embed=embed)318 return {"removed": rem}319class PrefixSupport(discord.ui.View):320 def __init__(self, modal: discord.ui.Modal):321 self.modal = modal()322 super().__init__(timeout=180)323 @discord.ui.button(label="Click Here")324 async def click_here(self, interaction: discord.Interaction, _: discord.ui.Button):325 await interaction.response.send_modal(self.modal)326# Decorator to auto add legacy prefix support327def mr_command(modal_class):328 def wrapper(f):329 @bot.command(name=f.__name__, help=f.__doc__)330 async def _(ctx: commands.Context):331 await ctx.send("To continue, click the below button", view=PrefixSupport(modal_class))332 return f333 return wrapper334class FSnowflake():335 """Blame discord"""336 def __init__(self, id):337 self.id: int = id338@bot.tree.command(guild=FSnowflake(id=secrets["gid"]))339async def invite(interaction: discord.Interaction, bot_id: str):340 if not bot_id.isdigit():341 return await interaction.response.send_message("Invalid bot id")342 return await interaction.response.send_message(f"https://discord.com/oauth2/authorize?client_id={bot_id}&scope=bot%20applications.commands&permissions=0")343@bot.tree.command(guild=FSnowflake(id=secrets["gid"]))344async def queue(interaction: discord.Interaction, show_all: bool = False):345 """Bot queue"""346 states = {}347 for state in list(tables.State):348 if not show_all and state not in (tables.State.PENDING, tables.State.UNDER_REVIEW):349 continue350 states[state] = await tables.BotQueue.select(tables.BotQueue.bot_id, tables.BotQueue.username).where(tables.BotQueue.state == state)351 msg = []352 msg_index = -1353 for key, bots in states.items():354 if not len(bots):355 continue356 msg.append(f"**{key.name} ({len(bots)})**\n\n")357 msg_index += 1358 for bot in bots:359 if len(msg) > 1900:360 msg.append("")361 msg_index += 1362 msg[msg_index] += f"{bot['bot_id']} ({bot['username']})\n"363 await interaction.response.send_message(msg[0])364 for msg in msg[1:]:365 await interaction.followup.send(msg)366@bot.tree.command(guild=FSnowflake(id=secrets["gid"]))367async def sync(interaction: discord.Interaction):368 """Syncs all commands"""369 await bot.tree.sync(guild=FSnowflake(id=secrets["gid"]))370 return await interaction.response.send_message("Done syncing")371@bot.tree.command(guild=FSnowflake(id=secrets["gid"]))372async def support(interaction: discord.Interaction):373 """Show the link to support"""374 await interaction.response.send_message("https://github.com/MetroReviews/support")375async def post_act(376 interaction: discord.Interaction, 377 list_info: dict, 378 action: tables.Action,379 key: str,380 bot_id: int,381 reason: str,382 resend: bool = False383):384 if len(reason) < 5:385 return await interaction.response.send_message("Reason too short (5 characters minimum)")386 if not interaction.guild:387 return388 389 if interaction.guild.id != secrets["gid"]:390 guild = bot.get_guild(secrets["gid"])391 try:392 roles = guild.get_member(interaction.user.id).roles393 except Exception as exc:394 return await interaction.response.send_message(f"You must have the `Reviewer` role to use this command. {exc}")395 else:396 roles = interaction.user.roles397 if not discord.utils.get(roles, id=secrets["reviewer"]):398 return await interaction.response.send_message("You must have the `Reviewer` role to use this command.")399 400 bot_data = await tables.BotQueue.select().where(tables.BotQueue.bot_id == bot_id).first()401 if not bot_data:402 return await interaction.response.send_message(f"This bot (`{bot_id}`) cannot be found") 403 if not resend:404 if action == tables.Action.CLAIM and bot_data["state"] != tables.State.PENDING:405 return await interaction.response.send_message("This bot cannot be claimed as it is not pending review? Maybe someone is testing it right noe?")406 elif action == tables.Action.UNCLAIM and bot_data["state"] != tables.State.UNDER_REVIEW:407 return await interaction.response.send_message("This bot cannot be unclaimed as it is not under review?")408 elif action == tables.Action.APPROVE and bot_data["state"] != tables.State.UNDER_REVIEW:409 return await interaction.response.send_message("This bot cannot be approved as it is not under review?")410 elif action == tables.Action.DENY and bot_data["state"] != tables.State.UNDER_REVIEW:411 return await interaction.response.send_message("This bot cannot be denied as it is not under review?")412 if action == tables.Action.CLAIM:413 cls = tables.State.UNDER_REVIEW414 if not resend:415 await tables.BotQueue.update(reviewer=interaction.user.id).where(tables.BotQueue.bot_id == bot_id)416 417 # Make new server using discord api418 try:419 created_guild = await bot.create_guild(name=f"{bot_id} testing")420 channel = await created_guild.create_text_channel(name="do-not-delete-this-channel")421 invite = await channel.create_invite(reason="Bot Reviewer invite")422 await interaction.channel.send(f"**{interaction.user.mention}\nPlease join the following server to test the bot. If you do not do so within 1 minute (will increase, just for testing), this server will be deleted and the bot will be unclaimed!**\n\n{invite.url}\n\nYou can add the bot to the server using this link: https://discord.com/oauth2/authorize?client_id={bot_id}&permissions=0&guild_id={created_guild.id}&scope=bot%20applications.commands&disable_guild_select=true")423 await tables.BotQueue.update(invite_link=invite.url).where(tables.BotQueue.bot_id == bot_id)424 async def _task(guild: discord.Guild, bot_id: int):425 await asyncio.sleep(60)426 cached_guild = bot.get_guild(guild.id)427 if not cached_guild:428 return # All good429 if not cached_guild.owner_id:430 return await _task(guild, bot_id)431 if cached_guild.owner_id == bot.user.id:432 # Then the user has not joined the server in time433 await tables.BotQueue.update(invite_link=None).where(tables.BotQueue.bot_id == bot_id)434 try:435 await guild.delete()436 except discord.errors.Forbidden:437 return438 except Exception as exc:439 print(f"Failed to delete guild: {exc}")440 await interaction.channel.send(content=f"**{interaction.user.mention}\nYou have not joined the server in time. The bot will be unclaimed and the server has been deleted!**")441 await tables.BotQueue.update(state=tables.State.PENDING, reviewer=None).where(tables.BotQueue.bot_id == bot_id)442 asyncio.create_task(_task(created_guild, bot_id))443 print("Got here")444 except Exception as exc:445 return await interaction.response.send_message(f"Failed to create new server for testing: {exc}")446 elif action == tables.Action.UNCLAIM:447 cls = tables.State.PENDING448 elif action == tables.Action.APPROVE:449 cls = tables.State.APPROVED450 elif action == tables.Action.DENY:451 cls = tables.State.DENIED452 await tables.BotQueue.update(state=cls).where(tables.BotQueue.bot_id == bot_id)453 msg = f"**{action.name.title()}!**\n"454 await interaction.response.defer()455 for list in list_info:456 if list["state"] not in good_states:457 continue458 if list["id"] != bot_data["list_source"] and not bot_data["cross_add"]:459 # Send limited 460 data = {461 "bot_id": str(bot_data["bot_id"]), 462 "owner": str(bot_data["owner"]), 463 "extra_owners": bot_data["extra_owners"],464 "cross_add": False,465 "prefix": None, # Dont send prefix466 "description": "", # Dont send description467 "long_description": "", # Dont send ld468 "list_source": bot_data["list_source"],469 "nsfw": True, # Dont send nsfw470 "tags": ["this-shouldnt-be-set"], # Dont send tags471 "username": bot_data["username"], # Username is needed for approve 472 "added_at": bot_data["added_at"], 473 }474 else:475 data = bot_data476 try:477 async with aiohttp.ClientSession() as sess:478 async with sess.post(479 list[key], 480 headers={"Authorization": list["secret_key"], "User-Agent": "Frostpaw/0.1"}, 481 json=data | {482 "bot_id": str(bot_data["bot_id"]), 483 "owner": str(bot_data["owner"]), 484 "reason": reason or "STUB_REASON", 485 "reviewer": str(interaction.user.id), 486 "added_at": str(bot_data["added_at"]), 487 "list_source": str(bot_data["list_source"]),488 "owner": str(bot_data["owner"]),489 "extra_owners": [str(v) for v in bot_data["extra_owners"]]490 }491 ) as resp:492 msg += f"{list['name']} -> {resp.status}"493 try:494 json_d = await resp.text()495 if resp.headers.get("content-type", "").startswith("application/json"):496 json_d = orjson.loads(json_d)497 except Exception as exc:498 json_d = f"JSON deser failed {exc}"499 msg += f" ({json_d})\n"500 except Exception as exc:501 msg += f"{list['name']} -> {type(exc).__name__}: {exc}\n"502 503 # Post intent to actions504 await tables.BotAction.insert(505 tables.BotAction(bot_id=bot_id, reason=reason, reviewer=str(interaction.user.id), action=action, action_time=datetime.datetime.now(), list_source=bot_data["list_source"])506 )507 508 embed = discord.Embed(title="Bot Info", description=f"**Bot ID**: {bot_id}\n\n**Reason:** {reason}", color=discord.Color.green())509 class ResendView(discord.ui.View):510 def __init__(self, *args, **kwargs):511 super().__init__(timeout=120)512 513 @discord.ui.button(label="Resend")514 async def resend(self, interaction: discord.Interaction, _: discord.ui.Button):515 return await post_act(516 interaction, 517 list_info, 518 action,519 key,520 bot_id,521 reason,522 resend = True523 )524 await interaction.followup.send(msg, embeds=[embed], view=ResendView())525class Claim(discord.ui.Modal, title='Claim Bot'):526 bot_id = discord.ui.TextInput(label='Bot ID')527 resend = discord.ui.TextInput(label='Resend to other lists (owner only, T/F)', default="F")528 async def on_submit(self, interaction: discord.Interaction):529 try:530 bot_id = int(self.bot_id.value)531 except:532 return await interaction.response.send_message("Bot ID invalid") # Don't respond, so it gives error on their side533 534 list_info = await tables.BotList.select(tables.BotList.id, tables.BotList.name, tables.BotList.state, tables.BotList.claim_bot_api, tables.BotList.secret_key)535 resend = self.resend.value.lower() in ("t", "true")536 if resend and interaction.user.id not in secrets["owners"]:537 return await interaction.response.send_message("You are not an owner")538 return await post_act(interaction, list_info, tables.Action.CLAIM, "claim_bot_api", bot_id, "STUB_REASON", resend=resend)539class Unclaim(discord.ui.Modal, title='Unclaim Bot'):540 bot_id = discord.ui.TextInput(label='Bot ID')541 reason = discord.ui.TextInput(label='Reason', style=discord.TextStyle.paragraph, max_length=4000, min_length=5)542 resend = discord.ui.TextInput(label='Resend to other lists (owner only, T/F)', default="F")543 async def on_submit(self, interaction: discord.Interaction):544 try:545 bot_id = int(self.bot_id.value)546 except:547 return await interaction.response.send_message("Bot ID invalid") # Don't respond, so it gives error on their side548 list_info = await tables.BotList.select(tables.BotList.id, tables.BotList.name, tables.BotList.state, tables.BotList.unclaim_bot_api, tables.BotList.secret_key)549 resend = self.resend.value.lower() in ("t", "true")550 if resend and interaction.user.id not in secrets["owners"]:551 return await interaction.response.send_message("You are not an owner")552 return await post_act(interaction, list_info, tables.Action.UNCLAIM, "unclaim_bot_api", bot_id, self.reason.value, resend=resend)553class Approve(discord.ui.Modal, title='Approve Bot'):554 bot_id = discord.ui.TextInput(label='Bot ID')555 reason = discord.ui.TextInput(label='Reason', style=discord.TextStyle.paragraph, max_length=4000, min_length=5)556 resend = discord.ui.TextInput(label='Resend to other lists (owner only, T/F)', default="F")557 async def on_submit(self, interaction: discord.Interaction):558 try:559 bot_id = int(self.bot_id.value)560 except:561 return await interaction.response.send_message("Bot ID invalid") # Don't respond, so it gives error on their side562 list_info = await tables.BotList.select(tables.BotList.id, tables.BotList.name, tables.BotList.state, tables.BotList.approve_bot_api, tables.BotList.secret_key)563 resend = self.resend.value.lower() in ("t", "true")564 if resend and interaction.user.id not in secrets["owners"]:565 return await interaction.response.send_message("You are not an owner")566 return await post_act(interaction, list_info, tables.Action.APPROVE, "approve_bot_api", bot_id, self.reason.value, resend=resend)567class Deny(discord.ui.Modal, title='Deny Bot'):568 bot_id = discord.ui.TextInput(label='Bot ID')569 reason = discord.ui.TextInput(label='Reason', style=discord.TextStyle.paragraph, max_length=4000, min_length=5)570 resend = discord.ui.TextInput(label='Resend to other lists (owner only, T/F)', default="F")571 async def on_submit(self, interaction: discord.Interaction):572 try:573 bot_id = int(self.bot_id.value)574 except:575 return await interaction.response.send_message("Bot ID invalid") # Don't respond, so it gives error on their side576 list_info = await tables.BotList.select(tables.BotList.id, tables.BotList.name, tables.BotList.state, tables.BotList.deny_bot_api, tables.BotList.secret_key)577 resend = self.resend.value.lower() in ("t", "true")578 if resend and interaction.user.id not in secrets["owners"]:579 return await interaction.response.send_message("You are not an owner")580 return await post_act(interaction, list_info, tables.Action.DENY, "deny_bot_api", bot_id, self.reason.value, resend=resend)581@bot.tree.command(guild=FSnowflake(id=secrets["gid"]))582@mr_command(modal_class=Claim)583async def claim(interaction: discord.Interaction):584 """Claim a bot"""585 return await interaction.response.send_modal(Claim())586@bot.tree.command(guild=FSnowflake(id=secrets["gid"]))587@mr_command(modal_class=Unclaim)588async def unclaim(interaction: discord.Interaction):589 """Unclaims a bot"""590 return await interaction.response.send_modal(Unclaim())591@bot.tree.command(guild=FSnowflake(id=secrets["gid"]))592@mr_command(modal_class=Approve)593async def approve(interaction: discord.Interaction):594 """Approves a bot"""595 return await interaction.response.send_modal(Approve())596@bot.tree.command(guild=FSnowflake(id=secrets["gid"]))597@mr_command(modal_class=Deny)598async def deny(interaction: discord.Interaction):599 """Denies a bot"""600 return await interaction.response.send_modal(Deny())601@bot.event602async def on_ready():603 print("Client is now ready and up")604 await bot.tree.sync()605 await bot.tree.sync(guild=FSnowflake(id=secrets["gid"]))606 for cmd in bot.tree.walk_commands():607 print(cmd.name)608 609 for guild in bot.guilds:610 if guild.owner_id == bot.user.id:611 # Transfer ownership or delete612 if len(guild.members) == 1:613 await guild.delete()614 else:615 try:616 bot_id = int(guild.name.split(" ")[0])617 c = await guild.create_text_channel("never-remove-this")618 invite = await c.create_invite()619 await tables.BotQueue.update(invite_link=invite.url).where(tables.BotQueue.bot_id == bot_id)620 except Exception as e:621 print(e)622 await guild.edit(owner=guild.members[0])623 await guild.leave()624@bot.event625async def on_member_join(member: discord.Member):626 if member.guild.owner_id == bot.user.id:627 # This is a bot owned guild, transfer ownership and leave628 await member.guild.edit(owner=member)629 await member.guild.leave()630# Panel code631class FakeResponse():632 def __init__(self, ws: WebSocket):633 self.ws = ws634 async def send_message(self, 635 content, 636 *, 637 embed = None,638 embeds = [],639 **_,640 ):641 if embed:642 embeds.append(embed)643 await self.ws.send_json({"content": content, "embeds": [e.to_dict() for e in embeds]})644 async def defer(self, *args, **kwargs):645 await self.ws.send_json({"defer": True})646class FakeState:647 ...648class FakeWs():649 def __init__(self):650 self.resp = []651 self.state = FakeState()652 653 async def send_json(self, data):654 self.resp.append(data)655class FakeChannel():656 def __init__(self, ws: WebSocket):657 self.ws = ws658 self.id = 0659 async def send(self, 660 content, 661 *, 662 embed = None,663 embeds = [],664 **_,665 ):666 if embed:667 embeds.append(embed)668 await self.ws.send_json({"content": content, "embeds": [e.to_dict() for e in embeds]})669class FakeUser():670 def __init__(self, ws: WebSocket, id: int):671 self.ws = ws672 self.id = id673 self.roles = [FSnowflake(id=secrets["reviewer"])]674 self.mention = f"<@{id}>"675class FakeInteraction():676 def __init__(self, ws: WebSocket):677 self.response = FakeResponse(ws)678 self.followup = FakeChannel(ws)679 self.channel = FakeChannel(ws)680 self.user = FakeUser(ws, ws.state.user["user_id"])681 self.guild_id = secrets["gid"]682 self.guild = FSnowflake(id=secrets["gid"])683@app.get("/littlecloud/{bot_id}")684async def reapprove_bot(bot_id: int):685 list_info = await tables.BotList.select(tables.BotList.id, tables.BotList.name, tables.BotList.state, tables.BotList.approve_bot_api, tables.BotList.secret_key)686 687 bot = await tables.BotQueue.select(tables.BotQueue.state).where(tables.BotQueue.bot_id == bot_id).first()688 if not bot or bot["state"] != tables.State.APPROVED:689 return HTMLResponse("Bot is not approved and cannot be reapproved!")690 ws = FakeWs()691 ws.state.user = {692 "user_id": 968734728465289248 # Reapprove as system693 }694 await post_act(FakeInteraction(ws), list_info, tables.Action.APPROVE, "approve_bot_api", bot_id, "Already approved, readding due to errors (Automated Action)", resend=True)695 return ws.resp696@app.get("/_panel/strikestone", tags=["Panel (Internal)"])697def get_oauth2():698 return ORJSONResponse({"url": f"https://discord.com/api/oauth2/authorize?client_id={bot.application_id}&permissions=0&scope=identify%20guilds&response_type=code&redirect_uri=https://catnip.metrobots.xyz/_panel/frostpaw"})699class StarClan():700 def __init__(self):701 self.ws_list = []702 703 def add(self, ws: WebSocket):704 self.ws_list.append(ws)705 def remove(self, ws: WebSocket):706 self.ws_list.remove(ws)707sc = StarClan()708class SPL:709 unsuppprted = "U"710 auth_fail = "AF"711 out_of_date = "OD"712 done = "D"713class Reason(pydantic.BaseModel):714 reason: str715@app.post("/bots/{bot_id}/approve")716async def approve_bot(bot_id: int, reviewer: int, reason: Reason, list_id: uuid.UUID, auth: str = Depends(auth_header)):717 if (auth := await _auth(list_id, auth)):718 return auth 719 list_info = await tables.BotList.select(tables.BotList.id, tables.BotList.name, tables.BotList.state, tables.BotList.approve_bot_api, tables.BotList.secret_key)720 721 ws = FakeWs()722 ws.state.user = {723 "user_id": reviewer724 }725 await tables.BotQueue.update(state = tables.State.UNDER_REVIEW).where(tables.BotQueue.bot_id == bot_id)726 await post_act(FakeInteraction(ws), list_info, tables.Action.APPROVE, "approve_bot_api", bot_id, reason.reason)727 return ws.resp728@app.post("/bots/{bot_id}/deny")729async def deny_bot(bot_id: int, reviewer: int, reason: Reason, list_id: uuid.UUID, auth: str = Depends(auth_header)):730 if (auth := await _auth(list_id, auth)):731 return auth732 list_info = await tables.BotList.select(tables.BotList.id, tables.BotList.name, tables.BotList.state, tables.BotList.deny_bot_api, tables.BotList.secret_key)733 ws = FakeWs()734 ws.state.user = {735 "user_id": reviewer736 }737 await tables.BotQueue.update(state = tables.State.UNDER_REVIEW).where(tables.BotQueue.bot_id == bot_id)738 await post_act(FakeInteraction(ws), list_info, tables.Action.DENY, "deny_bot_api", bot_id, reason.reason)739 return ws.resp740@app.websocket("/_panel/starclan")741async def starclan_panel(ws: WebSocket, ticket: str, nonce: str):742 if ws.headers.get("Origin") != "https://metrobots.xyz":743 await ws.accept()744 await ws.send_json({"resp": "spld", "e": SPL.unsuppprted})745 await ws.close(code=4009)746 return747 await ws.accept()748 if nonce != "ashfur-v1":749 await ws.send_json({"resp": "spld", "e": SPL.out_of_date})750 return751 try:752 ws.state.ticket = orjson.loads(urlsafe_b64decode(ticket))753 if "nonce" not in ws.state.ticket.keys() or "user_id" not in ws.state.ticket.keys():754 await ws.send_json({"resp": "spld", "e": SPL.auth_fail, "hint": "Invalid ticket"})755 await ws.close(code=4009)756 return757 758 ws.state.ticket["user_id"] = int(ws.state.ticket["user_id"])759 user = await tables.Users.select().where(tables.Users.user_id==ws.state.ticket["user_id"], tables.Users.nonce==ws.state.ticket["nonce"]).first()760 if not user:761 await ws.send_json({"resp": "spld", "e": SPL.auth_fail})762 await ws.close(code=4009)763 return764 765 ws.state.user = user766 except Exception as exc:767 await ws.send_json({"resp": "spld", "e": SPL.auth_fail, "hint": str(exc)})768 await ws.close(code=4009)769 return770 sc.add(ws)771 try:772 while True:773 data = await ws.receive_json()774 if data["act"] == "claim":775 list_info = await tables.BotList.select(tables.BotList.id, tables.BotList.name, tables.BotList.state, tables.BotList.claim_bot_api, tables.BotList.secret_key)776 await post_act(FakeInteraction(ws), list_info, tables.Action.CLAIM, "claim_bot_api", int(data["id"]), "STUB_REASON")777 except WebSocketDisconnect:778 sc.remove(ws)779 await ws.close(code=4008)780 except Exception as exc:781 print(exc)782 sc.remove(ws)783 await ws.close(code=4009)784@app.get("/_panel/mapleshade", tags=["Panel (Internal)"])785async def get_panel_access(ticket: str):786 try:787 ticket = orjson.loads(urlsafe_b64decode(ticket))788 except:789 return {"access": False}790 if "nonce" not in ticket.keys() or "user_id" not in ticket.keys():791 return {"access": False}792 ticket["user_id"] = int(ticket["user_id"])793 user = await tables.Users.select().where(tables.Users.user_id==ticket["user_id"], tables.Users.nonce==ticket["nonce"]).first()794 if not user:795 return {"access": False}796 guild = bot.get_guild(secrets["gid"])797 if not guild:798 return {"access": False}799 member = guild.get_member(user["user_id"])800 if not member:801 return {"access": False}802 if discord.utils.get(member.roles, id=secrets["reviewer"]):803 return {"access": True}804 return {"access": False}805@app.get("/_panel/frostpaw", tags=["Panel (Internal)"])806async def complete_oauth2(request: Request, code: str):807 payload = {808 'grant_type': 'authorization_code',809 'code': code,810 'client_id': bot.application_id,811 'redirect_uri': "https://catnip.metrobots.xyz/_panel/frostpaw",812 'client_secret': secrets["client_secret"],813 }814 async with aiohttp.ClientSession() as sess:815 async with sess.post("https://discord.com/api/v10/oauth2/token", data=payload) as resp:816 if resp.status != 200:817 return await resp.json()818 data = await resp.json()819 scope = data["scope"].split(" ")820 if "identify" not in scope or "guilds" not in scope:821 return {"error": f"Invalid scopes, got {data['scope']} but have {scope}"}822 823 if data["token_type"] != "Bearer":824 return {"error": f"Invalid token type, got {data['token_type']}"}825 826 # Fetch user info827 async with sess.get(f"https://discord.com/api/v10/users/@me", headers={"Authorization": f"Bearer {data['access_token']}"}) as resp:828 if resp.status != 200:829 return await resp.json()830 user = await resp.json()831 # Save the token832 nonce = _secrets.token_urlsafe()833 try:834 await tables.Users.insert(835 tables.Users(836 user_id=int(user["id"]),837 nonce=nonce838 )839 )840 except Exception:841 pass842 old_nonce = await tables.Users.select(tables.Users.nonce).where(tables.Users.user_id == int(user["id"])).first()843 ticket = {844 "nonce": old_nonce["nonce"],845 "user_id": str(user["id"]),846 "username": user["username"], # Ignored during actual auth847 "disc": user["discriminator"],848 "avatar": user["avatar"],849 }850 ticket = urlsafe_b64encode(orjson.dumps(ticket)).decode()851 return RedirectResponse(852 f"https://metrobots.xyz/curlfeather?ticket={ticket}"...
tableUpdater.js
Source:tableUpdater.js
1// if xajax has not yet been initialized, wait a second and try again2// once xajax has been initialized, then install the table command3// handlers. 4installTableUpdater = function() {5 var xjxReady = false;6 try {7 if (xajax) xjxReady = true;8 } catch (e) {9 }10 if (false == xjxReady) {11 setTimeout('installTableUpdater();', 1000);12 return;13 }14 try {15 if ('undefined' == typeof xajax.ext.tables)16 xajax.ext.tables = {};17 } catch (e) {18 xajax.ext = {};19 xajax.ext.tables = {};20 }21 // internal helper functions22 xajax.ext.tables.internal = {};23 xajax.ext.tables.internal.createTable = function(table) {24 if ('string' != typeof (table))25 throw { name: 'TableError', message: 'Invalid table name specified.' }26 var newTable = document.createElement('table');27 newTable.id = table;28 // save the column configuration29 xajax.ext.tables.appendHeader(table + '_header', newTable);30 xajax.ext.tables.appendBody(table + '_body', newTable);31 xajax.ext.tables.appendFooter(table + '_footer', newTable);32 return newTable;33 }34 xajax.ext.tables.internal.createRow = function(objects, id) {35 var row = document.createElement('tr');36 if (null != id)37 row.id = id;38 return row;39 }40 xajax.ext.tables.internal.createCell = function(objects, id) {41 var cell = document.createElement('td');42 if (null != id)43 cell.id = id;44 cell.innerHTML = '...';45 return cell;46 }47 xajax.ext.tables.internal.getColumnNumber = function(objects, cell) {48 var position;49 var columns = objects.header.getElementsByTagName('td');50 for (var column = 0; column < columns.length; ++column)51 if (columns[column].id == cell)52 return column;53 throw { name: 'TableError', message: 'Column not found. (getColumnNumber)' }54 return undefined;55 }56 xajax.ext.tables.internal.objectify = function(params, required) {57 if ('undefined' == typeof params.source)58 return false;59 var source = params.source;60 if ('string' == typeof (source))61 source = xajax.$(source);62 if ('TBODY' == source.nodeName) {63 params.table = source.parentNode;64 } else if ('TABLE' == source.nodeName) {65 params.table = source;66 } else if ('TR' == source.nodeName) {67 params.row = source;68 params.body = source.parentNode;69 params.table = source.parentNode.parentNode;70 } else if ('TD' == source.nodeName) {71 params.cell = source;72 params.row = source.parentNode;73 params.columns = params.row.getElementsByTagName('TD');74 for (var column = 0; 'undefined' == typeof params.column && column < params.columns.length; ++column)75 if (params.cell.id == params.columns[column].id)76 params.column = column;77 params.table = source.parentNode.parentNode.parentNode;78 } else if ('THEAD' == source.nodeName) {79 params.table = source.parentNode;80 } else if ('TFOOT' == source.nodeName) {81 params.table = source.parentNode;82 } else83 params.source = source;84 85 var bodies = params.table.getElementsByTagName('TBODY');86 if (0 < bodies.length)87 params.body = bodies[0];88 var headers = params.table.getElementsByTagName('THEAD');89 if (0 < headers.length)90 params.header = headers[0];91 var feet = params.table.getElementsByTagName('TFOOT');92 if (0 < feet.length)93 params.footer = feet[0];94 if ('undefined' != typeof params.body)95 params.rows = params.body.getElementsByTagName('TR');96 if ('undefined' != typeof params.row)97 params.cells = params.row.getElementsByTagName('TD');98 if ('undefined' != typeof params.header)99 params.columns = params.header.getElementsByTagName('TD');100 101 if ('undefined' == typeof required)102 return true;103 104 for (var index = 0; index < required.length; ++index) {105 var require = required[index];106 var is_defined = false;107 eval('is_defined = (undefined != params.' + require + ');');108 if (false == is_defined)109 throw { name: 'TableError', message: 'Unable to locate required object [' + require + '].' };110 }111 112 return true;113 }114 // table115 xajax.ext.tables.append = function(table, parent) {116 if ('string' == typeof (parent))117 parent = xajax.$(parent);118 parent.appendChild(xajax.ext.tables.internal.createTable(table));119 }120 xajax.ext.tables.insert = function(table, parent, before) {121 if ('string' == typeof (parent))122 parent = xajax.$(parent);123 if ('string' == typeof (before))124 before = xajax.$(before);125 parent.insertBefore(xajax.ext.tables.internal.createTable(table), before);126 }127 xajax.ext.tables.remove = function(table) {128 var objects = { source: table };129 xajax.ext.tables.internal.objectify(objects, ['table']);130 objects.table.parentNode.removeChild(objects.table);131 }132 xajax.ext.tables.appendHeader = function(id, table) {133 var objects = { source: table };134 xajax.ext.tables.internal.objectify(objects, ['table']);135 if ('undefined' == typeof objects.header) {136 var thead = document.createElement('thead');137 if (null != id)138 thead.id = id;139 objects.header = thead;140 thead.appendChild(xajax.ext.tables.internal.createRow(objects, null));141 if ('undefined' == typeof objects.table.firstChild)142 table.appendChild(thead);143 else144 table.insertBefore(thead, table.firstChild);145 }146 }147 xajax.ext.tables.appendBody = function(id, table) {148 var objects = { source: table };149 xajax.ext.tables.internal.objectify(objects, ['table']);150 if ('undefined' == typeof objects.body) {151 var tbody = document.createElement('tbody');152 if (null != id)153 tbody.id = id;154 objects.body = tbody;155 }156 if ('undefined' != typeof objects.rows) {157 for (var rn = 0; rn < objects.rows.length; ++rn) {158 var row = objects.rows[rn];159 objects.table.removeChild(row);160 objects.body.appendChild(row);161 }162 }163 if ('undefined' != typeof objects.footer)164 objects.table.insertBefore(objects.body, objects.footer);165 else166 objects.table.appendChild(objects.body);167 }168 xajax.ext.tables.appendFooter = function(id, table) {169 var objects = { source: table }170 xajax.ext.tables.internal.objectify(objects, ['table']);171 if ('undefined' == typeof objects.footer) {172 var tfoot = document.createElement('tfoot');173 if (null != id)174 tfoot.id = id;175 objects.footer = tfoot;176 tfoot.appendChild(xajax.ext.tables.internal.createRow(objects, null));177 objects.table.appendChild(tfoot);178 }179 }180 // rows181 xajax.ext.tables.rows = {}182 xajax.ext.tables.rows.internal = {}183 xajax.ext.tables.rows.internal.calculateRow = function(objects, position) {184 if ('undefined' == typeof position)185 throw { name: 'TableError', message: 'Missing row number / id.' }186 if ('undefined' == typeof objects.row)187 if ('undefined' != typeof objects.rows)188 if ('undefined' != typeof objects.rows[position])189 objects.row = objects.rows[position];190 if ('undefined' == typeof objects.row)191 objects.row = xajax.$(position);192 if ('undefined' == typeof objects.row)193 throw { name: 'TableError', message: 'Invalid row number / row id specified.' }194 }195 xajax.ext.tables.rows.append = function(id, table) {196 var objects = { source: table }197 xajax.ext.tables.internal.objectify(objects, ['table', 'body']);198 var row = xajax.ext.tables.internal.createRow(objects, id);199 if ('undefined' != typeof objects.columns) {200 for (var column = 0; column < objects.columns.length; ++column) {201 var cell = xajax.ext.tables.internal.createCell(objects, null);202 cell.innerHTML = '...';203 row.appendChild(cell);204 }205 }206 objects.body.appendChild(row);207 }208 xajax.ext.tables.rows.insert = function(id, source, position) {209 var objects = { source: source }210 xajax.ext.tables.internal.objectify(objects, ['table', 'body']);211 if ('undefined' == typeof objects.row)212 xajax.ext.tables.rows.internal.calculateRow(objects, position);213 var row = xajax.ext.tables.internal.createRow(objects, id);214 if ('undefined' != typeof objects.columns) {215 for (var column = 0; column < objects.columns.length; ++column) {216 var cell = xajax.ext.tables.internal.createCell(objects, null);217 cell.innerHTML = '...';218 row.appendChild(cell);219 }220 }221 objects.body.insertBefore(row, objects.row);222 }223 xajax.ext.tables.rows.replace = function(id, source, position) {224 var objects = { source: source }225 xajax.ext.tables.internal.objectify(objects, ['table', 'body']);226 if ('undefined' == typeof objects.row)227 xajax.ext.tables.rows.internal.calculateRow(objects, position);228 var row = xajax.ext.tables.internal.createRow(objects, id);229 if ('undefined' != typeof objects.columns) {230 for (var column = 0; column < objects.columns.length; ++column) {231 var cell = xajax.ext.tables.internal.createCell(objects, null);232 cell.innerHTML = '...';233 row.appendChild(cell);234 }235 }236 objects.body.insertBefore(row, objects.row);237 objects.body.removeChild(objects.row);238 }239 xajax.ext.tables.rows.remove = function(source, position) {240 var objects = { source: source }241 xajax.ext.tables.internal.objectify(objects, ['table', 'body']);242 if ('undefined' == typeof objects.row)243 xajax.ext.tables.rows.internal.calculateRow(objects, position);244 objects.body.removeChild(objects.row);245 }246 xajax.ext.tables.rows.assignProperty = function(value, source, position, property) {247 var objects = { source: source }248 xajax.ext.tables.internal.objectify(objects, ['table', 'body', 'header']);249 if ('undefined' == typeof objects.row)250 xajax.ext.tables.rows.internal.calculateRow(objects, position);251 if ('undefined' != typeof property)252 eval('objects.row.' + property + ' = value;');253 }254 xajax.ext.tables.rows.assign = function(values, source, position, start_column) {255 var objects = { source: source }256 xajax.ext.tables.internal.objectify(objects, ['table', 'body', 'header']);257 if ('undefined' == typeof objects.row)258 xajax.ext.tables.rows.internal.calculateRow(objects, position);259 if ('undefined' == typeof start_column)260 start_column = 0;261 for (var column = 0; column < values.length; ++column)262 xajax.ext.tables.cells.assign(values[column], objects.row, start_column + column);263 }264 // columns265 xajax.ext.tables.columns = {}266 xajax.ext.tables.columns.internal = {}267 xajax.ext.tables.columns.internal.calculateColumn = function(objects, position) {268 if ('undefined' == typeof position)269 throw { name: 'TableError', message: 'Missing column number / id.' }270 if ('undefined' == typeof objects.column)271 if ('undefined' != typeof objects.columns)272 if ('undefined' != typeof objects.columns[position])273 objects.column = position;274 if ('undefined' == typeof objects.column)275 for (var column = 0; 'undefined' == typeof objects.column && column < objects.columns.length; ++column)276 if (objects.columns[column].id == position)277 objects.column = column;278 if ('undefined' == typeof objects.column)279 throw { name: 'TableError', message: 'Invalid column number / row id specified.' }280 }281 xajax.ext.tables.columns.append = function(column_definition, table) {282 var objects = { source: table }283 xajax.ext.tables.internal.objectify(objects, ['table', 'header', 'body']);284 var cell = xajax.ext.tables.internal.createCell(objects, column_definition.id);285 if ('undefined' != typeof column_definition.name)286 cell.innerHTML = column_definition.name;287 objects.header.firstChild.appendChild(cell);288 if ('undefined' != typeof objects.rows)289 for (var i = 0; i < objects.rows.length; ++i)290 xajax.ext.tables.cells.append({id: null}, objects.rows[i]);291 }292 xajax.ext.tables.columns.insert = function(column_definition, source, position) {293 var objects = { source: source }294 xajax.ext.tables.internal.objectify(objects, ['table', 'header']);295 if ('undefined' == typeof objects.column)296 xajax.ext.tables.columns.internal.calculateColumn(objects, position);297 var column = xajax.ext.tables.internal.createCell(objects, column_definition.id);298 if ('undefined' != typeof column_definition.name)299 column.innerHTML = column_definition.name;300 objects.header.firstChild.insertBefore(column, objects.columns[objects.column]);301 if ('undefined' != typeof objects.rows)302 for (var i = 0; i < objects.rows.length; ++i)303 xajax.ext.tables.cells.insert({id: null}, objects.rows[i], objects.column);304 }305 xajax.ext.tables.columns.replace = function(column_definition, source, position) {306 var objects = { source: source }307 xajax.ext.tables.internal.objectify(objects, ['table', 'header', 'columns']);308 if ('undefined' == typeof objects.column)309 xajax.ext.tables.columns.internal.calculateColumn(objects, position);310 var before = objects.columns[objects.column];311 var column = xajax.ext.tables.internal.createCell(objects, column_definition.id);312 if ('undefined' != typeof column_definition.name)313 column.innerHTML = column_definition.name;314 objects.header.firstChild.insertBefore(column, before);315 objects.header.firstChild.removeChild(before);316 if ('undefined' != typeof objects.rows)317 for (var i = 0; i < objects.rows.length; ++i)318 xajax.ext.tables.cells.replace({id: null}, objects.rows[i], objects.column);319 }320 xajax.ext.tables.columns.remove = function(source, position) {321 var objects = { source: source }322 xajax.ext.tables.internal.objectify(objects, ['table', 'header']);323 if ('undefined' == typeof objects.column)324 xajax.ext.tables.columns.internal.calculateColumn(objects, position);325 objects.header.firstChild.removeChild(objects.columns[objects.column]);326 if ('undefined' != typeof objects.rows)327 for (var i = 0; i < objects.rows.length; ++i)328 xajax.ext.tables.cells.remove(objects.rows[i], objects.column);329 }330 xajax.ext.tables.columns.assign = function(values, source, position, start_row) {331 var objects = { source: source }332 xajax.ext.tables.internal.objectify(objects, ['table', 'cell']);333 if ('undefined' == typeof objects.column)334 xajax.ext.tables.columns.internal.calculateColumn(objects, position);335 for (var row = 0; row < values.length; ++row)336 xajax.ext.tables.cells.assign(values[row], objects.rows[start_row + row], objects.column);337 }338 xajax.ext.tables.columns.assignProperty = function(value, source, position, property) {339 var objects = { source: source }340 xajax.ext.tables.internal.objectify(objects, ['table', 'cell']);341 if ('undefined' == typeof objects.column)342 xajax.ext.tables.columns.internal.calculateColumn(objects, position);343 for (var row = 0; row < objects.rows.length; ++row)344 xajax.ext.tables.cells.assignProperty(value, objects.rows[row], objects.column, property);345 }346 // cells347 xajax.ext.tables.cells = {}348 xajax.ext.tables.cells.internal = {}349 xajax.ext.tables.cells.internal.calculateCell = function(objects, position) {350 if ('undefined' == typeof position)351 throw { name: 'TableError', message: 'Missing cell number / id.' }352 if ('undefined' == typeof objects.cell)353 if ('undefined' != typeof objects.cells)354 if ('undefined' != typeof objects.cells[position])355 objects.cell = objects.cells[position];356 if ('undefined' == typeof objects.cell)357 if ('undefined' != typeof objects.columns)358 for (var column = 0; 'undefined' == typeof objects.cell && column < objects.columns.length; ++column)359 if (objects.columns[column].id == position)360 objects.cell = objects.cells[column];361 if ('undefined' == typeof objects.cell)362 throw { name: 'TableError', message: 'Invalid cell number / id specified.' }363 }364 xajax.ext.tables.cells.append = function(cell_definition, source) {365 var objects = { source: source }366 xajax.ext.tables.internal.objectify(objects, ['table', 'row']);367 var cell = xajax.ext.tables.internal.createCell(objects, cell_definition.id);368 if ('undefined' != typeof cell_definition.name)369 cell.innerHTML = cell_definition.name;370 objects.row.appendChild(cell);371 }372 xajax.ext.tables.cells.insert = function(cell_definition, source, position) {373 var objects = { source: source }374 xajax.ext.tables.internal.objectify(objects, ['table', 'row']);375 if ('undefined' == typeof objects.cell)376 xajax.ext.tables.cells.internal.calculateCell(objects, position);377 var cell = xajax.ext.tables.internal.createCell(objects, cell_definition.id);378 if ('undefined' != typeof cell_definition.name)379 cell.innerHTML = cell_definition.name;380 objects.row.insertBefore(cell, objects.cell);381 }382 xajax.ext.tables.cells.replace = function(cell_definition, source, position) {383 var objects = { source: source }384 xajax.ext.tables.internal.objectify(objects, ['table', 'row']);385 if ('undefined' == typeof objects.cell)386 xajax.ext.tables.cells.internal.calculateCell(objects, position);387 var cell = xajax.ext.tables.internal.createCell(objects, cell_definition.id);388 if ('undefined' != typeof cell_definition.name)389 cell.innerHTML = cell_definition.name;390 objects.row.insertBefore(cell, objects.cell);391 objects.row.removeChild(objects.cell);392 }393 xajax.ext.tables.cells.remove = function(source, position) {394 var objects = { source: source }395 xajax.ext.tables.internal.objectify(objects, ['table', 'row']);396 if ('undefined' == typeof objects.cell)397 xajax.ext.tables.cells.internal.calculateCell(objects, position);398 objects.row.removeChild(objects.cell);399 }400 xajax.ext.tables.cells.assign = function(value, source, position) {401 var objects = { source: source }402 xajax.ext.tables.internal.objectify(objects, ['table', 'row']);403 if ('undefined' == typeof objects.cell)404 xajax.ext.tables.cells.internal.calculateCell(objects, position);405 objects.cell.innerHTML = value;406 }407 xajax.ext.tables.cells.assignProperty = function(value, source, position, property) {408 var objects = { source: source }409 xajax.ext.tables.internal.objectify(objects, ['table', 'row']);410 if ('undefined' == typeof objects.cell)411 xajax.ext.tables.cells.internal.calculateCell(objects, position);412 eval('objects.cell.' + property + ' = value;');413 }414 // command handlers415 // tables416 xajax.command.handler.register('et_at', function(args) {417 args.fullName = 'ext.tables.append';418 xajax.ext.tables.append(args.data, args.id);419 return true;420 });421 xajax.command.handler.register('et_it', function(args) {422 args.fullName = 'ext.tables.insert';423 xajax.ext.tables.insert(args.data, args.id, args.pos);424 return true;425 });426 xajax.command.handler.register('et_dt', function(args) {427 args.fullName = 'ext.tables.remove';428 xajax.ext.tables.remove(args.data);429 return true;430 });431 // rows432 xajax.command.handler.register('et_ar', function(args) {433 args.fullName = 'ext.tables.rows.append';434 xajax.ext.tables.rows.append(args.data, args.id);435 return true;436 });437 xajax.command.handler.register('et_ir', function(args) {438 args.fullName = 'ext.tables.rows.insert';439 xajax.ext.tables.rows.insert(args.data, args.id, args.pos);440 return true;441 });442 xajax.command.handler.register('et_rr', function(args) {443 args.fullName = 'ext.tables.rows.replace';444 xajax.ext.tables.rows.replace(args.data, args.id, args.pos);445 return true;446 });447 xajax.command.handler.register('et_dr', function(args) {448 args.fullName = 'ext.tables.rows.remove';449 xajax.ext.tables.rows.remove(args.id, args.pos);450 return true;451 });452 xajax.command.handler.register('et_asr', function(args) {453 args.fullName = 'ext.tables.rows.assign';454 xajax.ext.tables.rows.assign(args.data, args.id, args.pos);455 return true;456 });457 xajax.command.handler.register('et_asrp', function(args) {458 args.fullName = 'ext.tables.rows.assignProperty';459 xajax.ext.tables.rows.assignProperty(args.data, args.id, args.pos, args.prop);460 });461 // columns462 xajax.command.handler.register('et_acol', function(args) {463 args.fullName = 'ext.tables.columns.append';464 xajax.ext.tables.columns.append(args.data, args.id);465 return true;466 });467 xajax.command.handler.register('et_icol', function(args) {468 args.fullName = 'ext.tables.columns.insert';469 xajax.ext.tables.columns.insert(args.data, args.id, args.pos);470 return true;471 });472 xajax.command.handler.register('et_rcol', function(args) {473 args.fullName = 'ext.tables.columns.replace';474 xajax.ext.tables.columns.replace(args.data, args.id, args.pos);475 return true;476 });477 xajax.command.handler.register('et_dcol', function(args) {478 args.fullName = 'ext.tables.columns.remove';479 xajax.ext.tables.columns.remove(args.id, args.pos);480 return true;481 });482 xajax.command.handler.register('et_ascol', function(args) {483 args.fullName = 'ext.tables.columns.assign';484 xajax.ext.tables.columns.assign(args.data, args.id, args.pos, args.type);485 return true;486 });487 xajax.command.handler.register('et_ascolp', function(args) {488 args.fullName = 'ext.tables.columns.assignProperty';489 xajax.ext.tables.columns.assignProperty(args.data, args.id, args.pos, args.prop);490 return true;491 });492 // cells493 xajax.command.handler.register('et_ac', function(args) {494 args.fullName = 'ext.tables.cells.append';495 xajax.ext.tables.cells.append(args.data, args.id);496 return true;497 });498 xajax.command.handler.register('et_ic', function(args) {499 args.fullName = 'ext.tables.cells.insert';500 xajax.ext.tables.cells.insert(args.data, args.id, args.pos);501 return true;502 });503 xajax.command.handler.register('et_rc', function(args) {504 args.fullName = 'ext.tables.cells.replace';505 xajax.ext.tables.cells.replace(args.data, args.id, args.pos);506 });507 xajax.command.handler.register('et_dc', function(args) {508 args.fullName = 'ext.tables.cells.remove';509 xajax.ext.tables.cells.remove(args.id, args.pos);510 return true;511 });512 xajax.command.handler.register('et_asc', function(args) {513 args.fullName = 'ext.tables.cells.assign';514 xajax.ext.tables.cells.assign(args.data, args.id, args.pos);515 return true;516 });517 xajax.command.handler.register('et_ascp', function(args) {518 args.fullName = 'ext.tables.cells.assignProperty';519 xajax.ext.tables.cells.assignProperty(args.data, args.id, args.pos, args.prop);520 return true;521 });522}...
test_common.py
Source:test_common.py
...30 assert df.equals(tables[0].df)31 filename = os.path.join(testdir, "anticlockwise_table_2.pdf")32 tables = camelot.read_pdf(filename, flavor="stream")33 assert df.equals(tables[0].df)34def test_stream_two_tables():35 df1 = pd.DataFrame(data_stream_two_tables_1)36 df2 = pd.DataFrame(data_stream_two_tables_2)37 filename = os.path.join(testdir, "tabula/12s0324.pdf")38 tables = camelot.read_pdf(filename, flavor="stream")39 assert len(tables) == 240 assert df1.equals(tables[0].df)41 assert df2.equals(tables[1].df)42def test_stream_table_regions():43 df = pd.DataFrame(data_stream_table_areas)44 filename = os.path.join(testdir, "tabula/us-007.pdf")45 tables = camelot.read_pdf(46 filename, flavor="stream", table_regions=["320,460,573,335"]47 )48 assert df.equals(tables[0].df)49def test_stream_table_areas():50 df = pd.DataFrame(data_stream_table_areas)51 filename = os.path.join(testdir, "tabula/us-007.pdf")52 tables = camelot.read_pdf(53 filename, flavor="stream", table_areas=["320,500,573,335"]54 )55 assert df.equals(tables[0].df)56def test_stream_columns():57 df = pd.DataFrame(data_stream_columns)58 filename = os.path.join(testdir, "mexican_towns.pdf")59 tables = camelot.read_pdf(60 filename, flavor="stream", columns=["67,180,230,425,475"], row_tol=1061 )62 assert df.equals(tables[0].df)63def test_stream_split_text():64 df = pd.DataFrame(data_stream_split_text)65 filename = os.path.join(testdir, "tabula/m27.pdf")66 tables = camelot.read_pdf(67 filename,68 flavor="stream",69 columns=["72,95,209,327,442,529,566,606,683"],70 split_text=True,71 )72 assert df.equals(tables[0].df)73def test_stream_flag_size():74 df = pd.DataFrame(data_stream_flag_size)75 filename = os.path.join(testdir, "superscript.pdf")76 tables = camelot.read_pdf(filename, flavor="stream", flag_size=True)77 assert df.equals(tables[0].df)78def test_stream_strip_text():79 df = pd.DataFrame(data_stream_strip_text)80 filename = os.path.join(testdir, "detect_vertical_false.pdf")81 tables = camelot.read_pdf(filename, flavor="stream", strip_text=" ,\n")82 assert df.equals(tables[0].df)83def test_stream_edge_tol():84 df = pd.DataFrame(data_stream_edge_tol)85 filename = os.path.join(testdir, "edge_tol.pdf")86 tables = camelot.read_pdf(filename, flavor="stream", edge_tol=500)87 assert df.equals(tables[0].df)88def test_stream_layout_kwargs():89 df = pd.DataFrame(data_stream_layout_kwargs)90 filename = os.path.join(testdir, "detect_vertical_false.pdf")91 tables = camelot.read_pdf(92 filename, flavor="stream", layout_kwargs={"detect_vertical": False}93 )94 assert df.equals(tables[0].df)95def test_lattice():96 df = pd.DataFrame(data_lattice)97 filename = os.path.join(98 testdir, "tabula/icdar2013-dataset/competition-dataset-us/us-030.pdf"99 )100 tables = camelot.read_pdf(filename, pages="2")101 assert df.equals(tables[0].df)102def test_lattice_table_rotated():103 df = pd.DataFrame(data_lattice_table_rotated)104 filename = os.path.join(testdir, "clockwise_table_1.pdf")105 tables = camelot.read_pdf(filename)106 assert df.equals(tables[0].df)107 filename = os.path.join(testdir, "anticlockwise_table_1.pdf")108 tables = camelot.read_pdf(filename)109 assert df.equals(tables[0].df)110def test_lattice_two_tables():111 df1 = pd.DataFrame(data_lattice_two_tables_1)112 df2 = pd.DataFrame(data_lattice_two_tables_2)113 filename = os.path.join(testdir, "twotables_2.pdf")114 tables = camelot.read_pdf(filename)115 assert len(tables) == 2116 assert df1.equals(tables[0].df)117 assert df2.equals(tables[1].df)118def test_lattice_table_regions():119 df = pd.DataFrame(data_lattice_table_regions)120 filename = os.path.join(testdir, "table_region.pdf")121 tables = camelot.read_pdf(filename, table_regions=["170,370,560,270"])122 assert df.equals(tables[0].df)123def test_lattice_table_areas():124 df = pd.DataFrame(data_lattice_table_areas)...
processor.test.ts
Source:processor.test.ts
1/**2 * Licensed to Cloudera, Inc. under one3 * or more contributor license agreements. See the NOTICE file4 * distributed with this work for additional information5 * regarding copyright ownership. Cloudera, Inc. licenses this file6 * to you under the Apache License, Version 2.0 (the7 * "License"); you may not use this file except in compliance8 * with the License. You may obtain a copy of the License at9 *10 * http://www.apache.org/licenses/LICENSE-2.011 *12 * Unless required by applicable law or agreed to in writing, software13 * distributed under the License is distributed on an "AS IS" BASIS,14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.15 * See the License for the specific language governing permissions and16 * limitations under the License.17 */18import { groupEntities } from './processor';19import { createTables } from '../test/utils';20import { Table } from './entities';21import { IEntity } from './interfaces';22describe('processor UTs', () => {23 test('Multiple unrelated entities (t0, t1, t2, t3, t4)', () => {24 const tableCount = 5;25 const entityGroups: Array<Array<IEntity>> = groupEntities(createTables(tableCount, 0), []);26 expect(entityGroups).toHaveLength(5);27 expect(entityGroups.flat()).toHaveLength(tableCount);28 });29 test('Related entities - Linked list (t0-t1-t2-t3-t4)', () => {30 const tableCount = 5;31 const tables: Array<Table> = createTables(tableCount, 2);32 const entityGroups: Array<Array<IEntity>> = groupEntities(tables, [33 {34 desc: '',35 left: tables[0].columns[1],36 right: tables[1].columns[0]37 },38 {39 desc: '',40 left: tables[1].columns[1],41 right: tables[2].columns[0]42 },43 {44 desc: '',45 left: tables[2].columns[1],46 right: tables[3].columns[0]47 },48 {49 desc: '',50 left: tables[3].columns[1],51 right: tables[4].columns[0]52 }53 ]);54 expect(entityGroups).toHaveLength(5);55 expect(entityGroups.flat()).toHaveLength(tableCount);56 });57 test('Related entities - Binary tree (t0-t1, t0-t2, t2-t3, t2-t4)', () => {58 const tableCount = 5;59 const tables: Array<Table> = createTables(tableCount, 3);60 const entityGroups: Array<Array<IEntity>> = groupEntities(tables, [61 {62 desc: '',63 left: tables[0].columns[1],64 right: tables[1].columns[0]65 },66 {67 desc: '',68 left: tables[0].columns[2],69 right: tables[2].columns[0]70 },71 {72 desc: '',73 left: tables[2].columns[1],74 right: tables[3].columns[0]75 },76 {77 desc: '',78 left: tables[2].columns[2],79 right: tables[4].columns[0]80 }81 ]);82 expect(entityGroups).toHaveLength(3);83 expect(entityGroups.flat()).toHaveLength(tableCount);84 });85 test('Related entities - Graph (t0-t1, t0-t2, t2-t3, t2-t4, t3-t0, t4-t0)', () => {86 // Adding back links in the above binary tree to simulate graph87 const tableCount = 5;88 const tables: Array<Table> = createTables(tableCount, 3);89 const entityGroups: Array<Array<IEntity>> = groupEntities(tables, [90 {91 desc: '',92 left: tables[0].columns[1],93 right: tables[1].columns[0]94 },95 {96 desc: '',97 left: tables[0].columns[2],98 right: tables[2].columns[0]99 },100 {101 desc: '',102 left: tables[2].columns[1],103 right: tables[3].columns[0]104 },105 {106 // Back link - 1107 desc: '',108 left: tables[3].columns[1],109 right: tables[0].columns[0]110 },111 {112 desc: '',113 left: tables[2].columns[2],114 right: tables[4].columns[0]115 },116 {117 // Back link - 2118 desc: '',119 left: tables[4].columns[2],120 right: tables[0].columns[0]121 }122 ]);123 expect(entityGroups).toHaveLength(3);124 expect(entityGroups.flat()).toHaveLength(tableCount);125 });126 test('Related entities - Self relation (t0-t0, t1)', () => {127 const tableCount = 2;128 const tables: Array<Table> = createTables(tableCount, 2);129 const entityGroups: Array<Array<IEntity>> = groupEntities(tables, [130 {131 desc: '',132 left: tables[0].columns[1],133 right: tables[0].columns[0]134 }135 ]);136 expect(entityGroups).toHaveLength(2);137 expect(entityGroups.flat()).toHaveLength(tableCount);138 });139 test('Related entities - Self relation + external reference (t0-t0, t0-t1)', () => {140 const tableCount = 2;141 const tables: Array<Table> = createTables(tableCount, 3);142 const entityGroups: Array<Array<IEntity>> = groupEntities(tables, [143 {144 desc: '',145 left: tables[0].columns[1],146 right: tables[0].columns[0]147 },148 {149 desc: '',150 left: tables[0].columns[2],151 right: tables[1].columns[0]152 }153 ]);154 expect(entityGroups).toHaveLength(2);155 expect(entityGroups.flat()).toHaveLength(tableCount);156 });157 test('Related entities - Cyclic relation (t0-t1, t1-t0)', () => {158 const tableCount = 2;159 const tables: Array<Table> = createTables(tableCount, 3);160 const entityGroups: Array<Array<IEntity>> = groupEntities(tables, [161 {162 desc: '',163 left: tables[0].columns[1],164 right: tables[1].columns[0]165 },166 {167 desc: '',168 left: tables[1].columns[1],169 right: tables[0].columns[0]170 }171 ]);172 expect(entityGroups).toHaveLength(2);173 expect(entityGroups.flat()).toHaveLength(tableCount);174 });175 test('Unrelated entity groups (t0-t1, t2-t3, t2-t4)', () => {176 const tableCount = 5;177 const tables: Array<Table> = createTables(tableCount, 2);178 const entityGroups: Array<Array<IEntity>> = groupEntities(tables, [179 {180 desc: '',181 left: tables[0].columns[1],182 right: tables[1].columns[0]183 },184 {185 desc: '',186 left: tables[2].columns[1],187 right: tables[3].columns[0]188 },189 {190 desc: '',191 left: tables[2].columns[1],192 right: tables[4].columns[0]193 }194 ]);195 expect(entityGroups).toHaveLength(4);196 expect(entityGroups.flat()).toHaveLength(tableCount);197 });...
Gruntfile.js
Source:Gruntfile.js
1'use strict';2module.exports = function(grunt) {3 // Project configuration.4 grunt.initConfig({5 // Metadata.6 pkg: grunt.file.readJSON('package.json'),7 banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +8 '<%= grunt.template.today("yyyy-mm-dd") %>\n' +9 '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +10 '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.company %>;' +11 ' Licensed <%= pkg.license %> */\n',12 // Task configuration.13 clean: {14 dependencies: ['dist/dependencies/'],15 post: ['dist/tmp/', 'dist/**/*.min.*']16 },17 copy: {18 jquery: {19 src: 'node_modules/jquery/dist/jquery.js',20 dest: 'dist/dependencies/jquery.js'21 },22 respond: {23 src: 'node_modules/respond.js/dest/respond.src.js',24 dest: 'dist/dependencies/respond.js'25 },26 qunit: {27 files: [{28 expand: true,29 flatten: true,30 src: [ 'node_modules/qunitjs/qunit/*' ],31 dest: 'dist/dependencies/',32 filter: 'isFile'33 }]34 }35 },36 concat: {37 options: {38 banner: '<%= banner %>',39 stripBanners: true40 },41 jsautoinit: {42 src: ['src/tables-init.js'],43 dest: 'dist/<%= pkg.name %>-init.js'44 },45 jsall: {46 src: [47 'src/tables.js',48 'src/tables.stack.js',49 'src/tables.btnmarkup.js',50 'src/tables.columntoggle.js',51 'src/tables.swipetoggle.js',52 'src/tables.sortable.js',53 'src/tables.minimap.js',54 'src/tables.modeswitch.js'55 ],56 dest: 'dist/<%= pkg.name %>.js'57 },58 jsstack: {59 src: [60 'src/tables.js',61 'src/tables.stack.js'62 ],63 dest: 'dist/stackonly/<%= pkg.name %>.stackonly.js'64 },65 cssall: {66 src: [67 'src/tables.css',68 'src/tables.toolbar.css',69 'src/tables.skin.css',70 'src/tables.stack.css',71 'src/tables.stack-default-breakpoint.css',72 'src/tables.swipetoggle.css',73 'src/tables.columntoggle.css',74 'src/tables.sortable.css',75 'src/tables.minimap.css'76 ],77 dest: 'dist/tmp/<%= pkg.name %>.myth.css'78 },79 cssbare: {80 src: [81 'src/tables.css',82 'src/tables.toolbar.css',83 'src/tables.stack.css',84 'src/tables.stack-default-breakpoint.css',85 'src/tables.swipetoggle.css',86 'src/tables.columntoggle.css',87 'src/tables.sortable.css',88 'src/tables.minimap.css',89 'src/tables.modeswitch.css'90 ],91 dest: 'dist/tmp/<%= pkg.name %>.bare.myth.css'92 },93 cssstack: {94 src: [95 'src/tables.css',96 'src/tables.stack.css',97 'src/tables.stack-default-breakpoint.css'98 ],99 dest: 'dist/tmp/<%= pkg.name %>.stackonly.myth.css'100 },101 cssstackmixinpre: {102 src: [103 'src/tables.css',104 'src/tables.stack.css'105 ],106 dest: 'dist/tmp/<%= pkg.name %>.stackonly.myth.scss'107 },108 cssstackmixinpost: {109 src: [110 'dist/tmp/<%= pkg.name %>.stackonly-sans-mixin.scss',111 'src/tables.stack-mixin.scss'112 ],113 dest: 'dist/stackonly/<%= pkg.name %>.stackonly.scss'114 }115 },116 qunit: {117 files: ['test/**/*.html']118 },119 jshint: {120 gruntfile: {121 options: {122 jshintrc: '.jshintrc'123 },124 src: 'Gruntfile.js'125 },126 src: {127 options: {128 jshintrc: 'src/.jshintrc'129 },130 src: ['src/**/*.js']131 },132 test: {133 options: {134 jshintrc: 'test/.jshintrc'135 },136 src: ['test/**/*.js']137 },138 },139 watch: {140 gruntfile: {141 files: '<%= jshint.gruntfile.src %>',142 tasks: ['jshint:gruntfile']143 },144 src: {145 files: ['<%= concat.cssall.src %>', '<%= concat.jsall.src %>', '<%= concat.jsautoinit.src %>'],146 tasks: ['src']147 },148 test: {149 files: '<%= jshint.test.src %>',150 tasks: ['jshint:test', 'qunit']151 },152 },153 uglify: {154 js: {155 files: {156 'dist/<%= pkg.name %>.min.js': [ 'dist/<%= pkg.name %>.js' ],157 'dist/stackonly/<%= pkg.name %>.stackonly.min.js': [ 'dist/stackonly/<%= pkg.name %>.stackonly.js' ]158 }159 }160 },161 cssmin: {162 css: {163 files: {164 'dist/<%= pkg.name %>.min.css': [ 'dist/<%= pkg.name %>.css' ],165 'dist/bare/<%= pkg.name %>.bare.min.css': [ 'dist/bare/<%= pkg.name %>.bare.css' ],166 'dist/stackonly/<%= pkg.name %>.stackonly.min.css': [ 'dist/stackonly/<%= pkg.name %>.stackonly.css' ]167 }168 }169 },170 bytesize: {171 dist: {172 src: [173 'dist/<%= pkg.name %>.min.css',174 'dist/<%= pkg.name %>.min.js',175 'dist/bare/<%= pkg.name %>.bare.min.css',176 'dist/stackonly/<%= pkg.name %>.stackonly.min.css',177 'dist/stackonly/<%= pkg.name %>.stackonly.min.js'178 ]179 }180 },181 'gh-pages': {182 options: {},183 src: ['dist/**/*', 'demo/**/*', 'test/**/*']184 },185 myth: {186 dist: {187 files: {188 'dist/<%= pkg.name %>.css': '<%= concat.cssall.dest %>',189 'dist/bare/<%= pkg.name %>.bare.css': '<%= concat.cssbare.dest %>',190 'dist/stackonly/<%= pkg.name %>.stackonly.css': '<%= concat.cssstack.dest %>',191 'dist/tmp/<%= pkg.name %>.stackonly-sans-mixin.scss': '<%= concat.cssstackmixinpre.dest %>'192 }193 }194 },195 compress: {196 main: {197 options: {198 archive: 'dist/tablesaw-<%= pkg.version %>.zip',199 mode: 'zip',200 pretty: true201 },202 files: [203 {expand: true, cwd: 'dist/', src: ['*'], dest: 'tablesaw/'},204 {expand: true, cwd: 'dist/', src: ['dependencies/*'], dest: 'tablesaw/'},205 {expand: true, cwd: 'dist/', src: ['stackonly/*'], dest: 'tablesaw/'},206 {expand: true, cwd: 'dist/', src: ['bare/*'], dest: 'tablesaw/'}207 ]208 }209 }210 });211 require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);212 // Default task.213 grunt.registerTask('travis', ['jshint', 'qunit']);214 grunt.registerTask('concat-pre', ['concat:jsautoinit', 'concat:jsall', 'concat:jsstack', 'concat:cssall', 'concat:cssbare', 'concat:cssstack', 'concat:cssstackmixinpre']);215 grunt.registerTask('concat-post', ['concat:cssstackmixinpost']);216 grunt.registerTask('src', ['concat-pre', 'myth', 'concat-post', 'clean:dependencies', 'copy', 'clean:post']);217 grunt.registerTask('filesize', ['uglify', 'cssmin', 'bytesize', 'clean:post']);218 grunt.registerTask('default', ['jshint', 'src', 'qunit', 'filesize']);219 // Deploy220 grunt.registerTask('deploy', ['default', 'gh-pages']);...
sql-hint-test.js
Source:sql-hint-test.js
1// CodeMirror, copyright (c) by Marijn Haverbeke and others2// Distributed under an MIT license: http://codemirror.net/LICENSE3(function() {4 var Pos = CodeMirror.Pos;5 var simpleTables = {6 "users": ["name", "score", "birthDate"],7 "xcountries": ["name", "population", "size"]8 };9 var schemaTables = {10 "schema.users": ["name", "score", "birthDate"],11 "schema.countries": ["name", "population", "size"]12 };13 var displayTextTables = [{14 text: "mytable",15 displayText: "mytable | The main table",16 columns: [{text: "id", displayText: "id | Unique ID"},17 {text: "name", displayText: "name | The name"}]18 }];19 namespace = "sql-hint_";20 function test(name, spec) {21 testCM(name, function(cm) {22 cm.setValue(spec.value);23 cm.setCursor(spec.cursor);24 var completion = CodeMirror.hint.sql(cm, {tables: spec.tables});25 if (!deepCompare(completion.list, spec.list))26 throw new Failure("Wrong completion results " + JSON.stringify(completion.list) + " vs " + JSON.stringify(spec.list));27 eqCharPos(completion.from, spec.from);28 eqCharPos(completion.to, spec.to);29 }, {30 value: spec.value,31 mode: spec.mode || "text/x-mysql"32 });33 }34 test("keywords", {35 value: "SEL",36 cursor: Pos(0, 3),37 list: ["SELECT"],38 from: Pos(0, 0),39 to: Pos(0, 3)40 });41 test("from", {42 value: "SELECT * fr",43 cursor: Pos(0, 11),44 list: ["FROM"],45 from: Pos(0, 9),46 to: Pos(0, 11)47 });48 test("table", {49 value: "SELECT xc",50 cursor: Pos(0, 9),51 tables: simpleTables,52 list: ["xcountries"],53 from: Pos(0, 7),54 to: Pos(0, 9)55 });56 test("columns", {57 value: "SELECT users.",58 cursor: Pos(0, 13),59 tables: simpleTables,60 list: ["users.name", "users.score", "users.birthDate"],61 from: Pos(0, 7),62 to: Pos(0, 13)63 });64 test("singlecolumn", {65 value: "SELECT users.na",66 cursor: Pos(0, 15),67 tables: simpleTables,68 list: ["users.name"],69 from: Pos(0, 7),70 to: Pos(0, 15)71 });72 test("quoted", {73 value: "SELECT `users`.`na",74 cursor: Pos(0, 18),75 tables: simpleTables,76 list: ["`users`.`name`"],77 from: Pos(0, 7),78 to: Pos(0, 18)79 });80 test("doublequoted", {81 value: "SELECT \"users\".\"na",82 cursor: Pos(0, 18),83 tables: simpleTables,84 list: ["\"users\".\"name\""],85 from: Pos(0, 7),86 to: Pos(0, 18),87 mode: "text/x-sqlite"88 });89 test("quotedcolumn", {90 value: "SELECT users.`na",91 cursor: Pos(0, 16),92 tables: simpleTables,93 list: ["`users`.`name`"],94 from: Pos(0, 7),95 to: Pos(0, 16)96 });97 test("doublequotedcolumn", {98 value: "SELECT users.\"na",99 cursor: Pos(0, 16),100 tables: simpleTables,101 list: ["\"users\".\"name\""],102 from: Pos(0, 7),103 to: Pos(0, 16),104 mode: "text/x-sqlite"105 });106 test("schema", {107 value: "SELECT schem",108 cursor: Pos(0, 12),109 tables: schemaTables,110 list: ["schema.users", "schema.countries",111 "SCHEMA", "SCHEMA_NAME", "SCHEMAS"],112 from: Pos(0, 7),113 to: Pos(0, 12)114 });115 test("schemaquoted", {116 value: "SELECT `sch",117 cursor: Pos(0, 11),118 tables: schemaTables,119 list: ["`schema`.`users`", "`schema`.`countries`"],120 from: Pos(0, 7),121 to: Pos(0, 11)122 });123 test("schemadoublequoted", {124 value: "SELECT \"sch",125 cursor: Pos(0, 11),126 tables: schemaTables,127 list: ["\"schema\".\"users\"", "\"schema\".\"countries\""],128 from: Pos(0, 7),129 to: Pos(0, 11),130 mode: "text/x-sqlite"131 });132 test("schemacolumn", {133 value: "SELECT schema.users.",134 cursor: Pos(0, 20),135 tables: schemaTables,136 list: ["schema.users.name",137 "schema.users.score",138 "schema.users.birthDate"],139 from: Pos(0, 7),140 to: Pos(0, 20)141 });142 test("schemacolumnquoted", {143 value: "SELECT `schema`.`users`.",144 cursor: Pos(0, 24),145 tables: schemaTables,146 list: ["`schema`.`users`.`name`",147 "`schema`.`users`.`score`",148 "`schema`.`users`.`birthDate`"],149 from: Pos(0, 7),150 to: Pos(0, 24)151 });152 test("schemacolumndoublequoted", {153 value: "SELECT \"schema\".\"users\".",154 cursor: Pos(0, 24),155 tables: schemaTables,156 list: ["\"schema\".\"users\".\"name\"",157 "\"schema\".\"users\".\"score\"",158 "\"schema\".\"users\".\"birthDate\""],159 from: Pos(0, 7),160 to: Pos(0, 24),161 mode: "text/x-sqlite"162 });163 test("displayText_table", {164 value: "SELECT myt",165 cursor: Pos(0, 10),166 tables: displayTextTables,167 list: [{text: "mytable", displayText: "mytable | The main table",}],168 from: Pos(0, 7),169 to: Pos(0, 10)170 });171 test("displayText_column", {172 value: "SELECT mytable.",173 cursor: Pos(0, 15),174 tables: displayTextTables,175 list: [{text: "mytable.id", displayText: "id | Unique ID"},176 {text: "mytable.name", displayText: "name | The name"}],177 from: Pos(0, 7),178 to: Pos(0, 15)179 });180 test("alias_complete", {181 value: "SELECT t. FROM users t",182 cursor: Pos(0, 9),183 tables: simpleTables,184 list: ["t.name", "t.score", "t.birthDate"],185 from: Pos(0, 7),186 to: Pos(0, 9)187 });188 test("alias_complete_with_displayText", {189 value: "SELECT t. FROM mytable t",190 cursor: Pos(0, 9),191 tables: displayTextTables,192 list: [{text: "t.id", displayText: "id | Unique ID"},193 {text: "t.name", displayText: "name | The name"}],194 from: Pos(0, 7),195 to: Pos(0, 9)196 })197 function deepCompare(a, b) {198 if (a === b) return true199 if (!(a && typeof a == "object") ||200 !(b && typeof b == "object")) return false201 var array = Array.isArray(a)202 if (Array.isArray(b) != array) return false203 if (array) {204 if (a.length != b.length) return false205 for (var i = 0; i < a.length; i++) if (!deepCompare(a[i], b[i])) return false206 } else {207 for (var p in a) if (!(p in b) || !deepCompare(a[p], b[p])) return false208 for (var p in b) if (!(p in a)) return false209 }210 return true211 }...
testing_tools_tests.py
Source:testing_tools_tests.py
1"""2Unit-tests for functions used in testing only.3build_input_node_lists_and_truth_tables(), feature A: determining node names correctly.40: no nodes are input to their update rule | 1: nodes are input to their update rule50: no constants are used in update rules | 1: constants are used in update rules6COMPLETE.7generate_node_name(), feature A: generating node name without parameters provided.8COMPLETE.9generate_node_name(), feature B: generating node name of length in given range.10COMPLETE.11generate_node_name(), feature C: failing to generate node name for invalid range.12COMPLETE.13"""14import unittest15from boolsi.testing_tools import build_predecessor_nodes_lists_and_truth_tables, generate_node_name16class TestingToolsTestCase(unittest.TestCase):17 def test_build_input_node_lists_and_truth_tables_A_0_0(self):18 update_rule_dict = {'A': 'B ',19 'B': 'not A'}20 expected_input_node_lists = [[1], [0]]21 expected_truth_tables = [{(False,): False, (True,): True},22 {(False,): True, (True,): False}]23 input_node_lists, truth_tables = build_predecessor_nodes_lists_and_truth_tables(update_rule_dict)24 self.assertEqual(input_node_lists, expected_input_node_lists)25 self.assertEqual(truth_tables, expected_truth_tables)26 def test_build_input_node_lists_and_truth_tables_A_0_1(self):27 update_rule_dict = {'A': '1 '}28 expected_input_node_lists = [[]]29 expected_truth_tables = [{(): True}]30 input_node_lists, truth_tables = build_predecessor_nodes_lists_and_truth_tables(update_rule_dict)31 self.assertEqual(input_node_lists, expected_input_node_lists)32 self.assertEqual(truth_tables, expected_truth_tables)33 def test_build_input_node_lists_and_truth_tables_A_1_0(self):34 update_rule_dict = {'A': 'not A '}35 expected_input_node_lists = [[0]]36 expected_truth_tables = [{(False,): True, (True,): False}]37 input_node_lists, truth_tables = build_predecessor_nodes_lists_and_truth_tables(update_rule_dict)38 self.assertEqual(input_node_lists, expected_input_node_lists)39 self.assertEqual(truth_tables, expected_truth_tables)40 def test_build_input_node_lists_and_truth_tables_A_1_1(self):41 update_rule_dict = {'A': '1 and not A'}42 expected_input_node_lists = [[0]]43 expected_truth_tables = [{(False,): True, (True,): False}]44 input_node_lists, truth_tables = build_predecessor_nodes_lists_and_truth_tables(update_rule_dict)45 self.assertEqual(input_node_lists, expected_input_node_lists)46 self.assertEqual(truth_tables, expected_truth_tables)47 def test_generate_node_name_A(self):48 node_name = generate_node_name()49 self.assertGreater(len(node_name), 0)50 def test_generate_node_name_B(self):51 length = 552 node_name = generate_node_name(min_length=length, max_length=length)53 self.assertEqual(len(node_name), length)54 def test_generate_node_name_C(self):55 min_length = 556 max_length = 457 node_name = generate_node_name(min_length=min_length, max_length=max_length)58 self.assertIsNone(node_name)...
tables.module.ts
Source:tables.module.ts
1import { NgModule } from '@angular/core';2import { CommonModule } from '@angular/common';3import { FormsModule } from '@angular/forms';4import { NgaModule } from '../../theme/nga.module';5import { Ng2SmartTableModule } from 'ng2-smart-table';6import { routing } from './tables.routing';7import { Tables } from './tables.component';8import { BasicTables } from './components/basicTables/basicTables.component';9import { BasicTablesService } from './components/basicTables/basicTables.service';10import { ResponsiveTable } from './components/basicTables/components/responsiveTable';11import { StripedTable } from './components/basicTables/components/stripedTable';12import { BorderedTable } from './components/basicTables/components/borderedTable';13import { HoverTable } from './components/basicTables/components/hoverTable';14import { CondensedTable } from './components/basicTables/components/condensedTable';15import { ContextualTable } from './components/basicTables/components/contextualTable';16import { SmartTables } from './components/smartTables/smartTables.component';17import { SmartTablesService } from './components/smartTables/smartTables.service';18@NgModule({19 imports: [20 CommonModule,21 FormsModule,22 NgaModule,23 routing,24 Ng2SmartTableModule,25 ],26 declarations: [27 Tables,28 BasicTables,29 HoverTable,30 BorderedTable,31 CondensedTable,32 StripedTable,33 ContextualTable,34 ResponsiveTable,35 SmartTables,36 ],37 providers: [38 BasicTablesService,39 SmartTablesService,40 ]41})42export class TablesModule {...
Using AI Code Generation
1var request = require('request-promise');2var fs = require('fs');3var url2 = '&_dyncharset=UTF-8&id=pcat17071&type=page&sc=Global&cp=1&nrp=&sp=&qp=&list=n&af=true&iht=n&usc=All+Categories&ks=960&keys=keys';4var output = 'output.txt';5var output2 = 'output2.txt';6var output3 = 'output3.txt';7var output4 = 'output4.txt';8var output5 = 'output5.txt';9var output6 = 'output6.txt';10var output7 = 'output7.txt';11var output8 = 'output8.txt';12var output9 = 'output9.txt';13var output10 = 'output10.txt';14var output11 = 'output11.txt';15var output12 = 'output12.txt';16var output13 = 'output13.txt';17var output14 = 'output14.txt';18var output15 = 'output15.txt';19var output16 = 'output16.txt';20var output17 = 'output17.txt';21var output18 = 'output18.txt';22var output19 = 'output19.txt';23var output20 = 'output20.txt';24var output21 = 'output21.txt';25var output22 = 'output22.txt';26var output23 = 'output23.txt';27var output24 = 'output24.txt';28var output25 = 'output25.txt';29var output26 = 'output26.txt';30var output27 = 'output27.txt';31var output28 = 'output28.txt';32var output29 = 'output29.txt';33var output30 = 'output30.txt';34var output31 = 'output31.txt';35var output32 = 'output32.txt';36var output33 = 'output33.txt';37var output34 = 'output34.txt';38var output35 = 'output35.txt';39var output36 = 'output36.txt';40var output37 = 'output37.txt';41var output38 = 'output38.txt';42var output39 = 'output39.txt';43var output40 = 'output40.txt';44var output41 = 'output41.txt';45var output42 = 'output42.txt';
Using AI Code Generation
1var bestFit = require('bestfit');2var tables = bestFit.tables();3tables.forEach(function(table){4 console.log(table.name);5});6var bestFit = require('bestfit');7var tables = bestFit.tables();8tables.forEach(function(table){9 console.log(table.columns);10});11var bestFit = require('bestfit');12var tables = bestFit.tables();13tables.forEach(function(table){14 console.log(table.data);15});16var bestFit = require('bestfit');
Using AI Code Generation
1var bf = new BestFit();2bf.readData("test4.dat");3var result = bf.tables(2, 1, 3);4print("Best fit is y = " + result.a + " + " + result.b + " * x");5print("Chi square = " + result.chiSquare);6print("Reduced chi square = " + result.reducedChiSquare);7print("Number of degrees of freedom = " + result.degreesOfFreedom);8print("Correlation coefficient = " + result.correlationCoefficient);9print("Standard deviation of a = " + result.standardDeviationOfA);10print("Standard deviation of b = " + result.standardDeviationOfB);11print("Standard error of a = " + result.standardErrorOfA);12print("Standard error of b = " + result.standardErrorOfB);13print("T value of a = " + result.tValueOfA);14print("T value of b = " + result.tValueOfB);15print("P value of a = " + result.pValueOfA);16print("P value of b = " + result.pValueOfB);17var file = new File("test4.txt");18file.open();19file.write("Best fit is y = " + result.a + " + " + result.b + " * x20");21file.write("Chi square = " + result.chiSquare + "22");23file.write("Reduced chi square = " + result.reducedChiSquare + "24");25file.write("Number of degrees of freedom = " + result.degreesOfFreedom + "26");27file.write("Correlation coefficient = " + result.correlationCoefficient + "28");29file.write("Standard deviation of a = " + result.standardDeviationOfA + "30");31file.write("Standard deviation of b = " + result.standardDeviationOf
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!