Merge branch 'master' into conquest_develop

conquest_develop
bobloy 4 years ago
commit 36d6e5c9bf

@ -17,8 +17,9 @@ Cog Function
| forcemention | **Alpha** | <details><summary>Mentions unmentionable roles</summary>Very simple cog, mention doesn't persist</details> |
| hangman | **Beta** | <details><summary>Play a game of hangman</summary>Some visual glitches and needs more customization</details> |
| howdoi | **Incomplete** | <details><summary>Ask coding questions and get results from StackExchange</summary>Not yet functional</details> |
| leaver | **Beta** | <details><summary>Send a message in a channel when a user leaves the server</summary>Seems to be functional, please report any bugs or suggestions</details> |
| infochannel | **Beta** | <details><summary>Create a channel to display server info</summary>Just released, please report bugs</details> |
| launchlib | **Beta** | <details><summary>Access rocket launch data</summary>Just released, please report bugs</details> |
| leaver | **Beta** | <details><summary>Send a message in a channel when a user leaves the server</summary>Seems to be functional, please report any bugs or suggestions</details> |
| lovecalculator | **Alpha** | <details><summary>Calculate the love between two users</summary>[Snap-Ons] Just updated to V3</details> |
| lseen | **Alpha** | <details><summary>Track when a member was last online</summary>Alpha release, please report bugs</details> |
| nudity | **Alpha** | <details><summary>Checks for NSFW images posted in non-NSFW channels</summary>Switched libraries, now functional</details> |

@ -3,7 +3,6 @@ import logging
import os
import pathlib
from datetime import datetime, timedelta
from typing import Literal
import discord
from chatterbot import ChatBot
@ -14,9 +13,8 @@ from redbot.core import Config, commands
from redbot.core.commands import Cog
from redbot.core.data_manager import cog_data_path
from redbot.core.utils.predicates import MessagePredicate
from redbot.core.utils import AsyncIter
log = logging.getLogger("red.fox_v3.chat")
log = logging.getLogger("red.fox_v3.chatter")
class ENG_LG:
@ -420,21 +418,18 @@ class Chatter(Cog):
for the message filtering
"""
###########
is_private = isinstance(message.channel, discord.abc.PrivateChannel)
# user_allowed check, will be replaced with self.bot.user_allowed or
# something similar once it's added
user_allowed = True
if len(message.content) < 2 or is_private or not user_allowed or message.author.bot:
if len(message.content) < 2 or message.author.bot:
return
if await self.bot.cog_disabled_in_guild(self, message.guild):
guild: discord.Guild = getattr(message, "guild", None)
if await self.bot.cog_disabled_in_guild(self, guild):
return
ctx: commands.Context = await self.bot.get_context(message)
if ctx.prefix is not None:
if ctx.prefix is not None: # Probably unnecessary, we're in on_message_without_command
return
###########
@ -454,23 +449,8 @@ class Chatter(Cog):
# print("not mentioned")
return
author = message.author
guild: discord.Guild = message.guild
channel: discord.TextChannel = message.channel
# if author.id != self.bot.user.id:
# if guild is None:
# to_strip = "@" + channel.me.display_name + " "
# else:
# to_strip = "@" + guild.me.display_name + " "
# text = message.clean_content
# if not text.startswith(to_strip):
# return
# text = text.replace(to_strip, "", 1)
# A bit more aggressive, could remove two mentions
# Or might not work at all, since mentionables are pre-cleaned_content
message.content = message.content.replace(prefix, "", 1)
text = message.clean_content

@ -89,7 +89,7 @@ class ExclusiveRole(Cog):
to_remove = (member_set - role_set) - {member.guild.default_role.id}
if to_remove and member_set & role_set:
to_remove = [discord.utils.get(member.guild.roles, id=id) for id in to_remove]
to_remove = [discord.utils.get(member.guild.roles, id=r_id) for r_id in to_remove]
await member.remove_roles(*to_remove, reason="Exclusive roles")
@commands.Cog.listener()

@ -0,0 +1,5 @@
from .launchlib import LaunchLib
def setup(bot):
bot.add_cog(LaunchLib(bot))

@ -0,0 +1,254 @@
countryISOMapping = {
"AFG": "AF",
"ALA": "AX",
"ALB": "AL",
"DZA": "DZ",
"ASM": "AS",
"AND": "AD",
"AGO": "AO",
"AIA": "AI",
"ATA": "AQ",
"ATG": "AG",
"ARG": "AR",
"ARM": "AM",
"ABW": "AW",
"AUS": "AU",
"AUT": "AT",
"AZE": "AZ",
"BHS": "BS",
"BHR": "BH",
"BGD": "BD",
"BRB": "BB",
"BLR": "BY",
"BEL": "BE",
"BLZ": "BZ",
"BEN": "BJ",
"BMU": "BM",
"BTN": "BT",
"BOL": "BO",
"BIH": "BA",
"BWA": "BW",
"BVT": "BV",
"BRA": "BR",
"VGB": "VG",
"IOT": "IO",
"BRN": "BN",
"BGR": "BG",
"BFA": "BF",
"BDI": "BI",
"KHM": "KH",
"CMR": "CM",
"CAN": "CA",
"CPV": "CV",
"CYM": "KY",
"CAF": "CF",
"TCD": "TD",
"CHL": "CL",
"CHN": "CN",
"HKG": "HK",
"MAC": "MO",
"CXR": "CX",
"CCK": "CC",
"COL": "CO",
"COM": "KM",
"COG": "CG",
"COD": "CD",
"COK": "CK",
"CRI": "CR",
"CIV": "CI",
"HRV": "HR",
"CUB": "CU",
"CYP": "CY",
"CZE": "CZ",
"DNK": "DK",
"DJI": "DJ",
"DMA": "DM",
"DOM": "DO",
"ECU": "EC",
"EGY": "EG",
"SLV": "SV",
"GNQ": "GQ",
"ERI": "ER",
"EST": "EE",
"ETH": "ET",
"FLK": "FK",
"FRO": "FO",
"FJI": "FJ",
"FIN": "FI",
"FRA": "FR",
"GUF": "GF",
"PYF": "PF",
"ATF": "TF",
"GAB": "GA",
"GMB": "GM",
"GEO": "GE",
"DEU": "DE",
"GHA": "GH",
"GIB": "GI",
"GRC": "GR",
"GRL": "GL",
"GRD": "GD",
"GLP": "GP",
"GUM": "GU",
"GTM": "GT",
"GGY": "GG",
"GIN": "GN",
"GNB": "GW",
"GUY": "GY",
"HTI": "HT",
"HMD": "HM",
"VAT": "VA",
"HND": "HN",
"HUN": "HU",
"ISL": "IS",
"IND": "IN",
"IDN": "ID",
"IRN": "IR",
"IRQ": "IQ",
"IRL": "IE",
"IMN": "IM",
"ISR": "IL",
"ITA": "IT",
"JAM": "JM",
"JPN": "JP",
"JEY": "JE",
"JOR": "JO",
"KAZ": "KZ",
"KEN": "KE",
"KIR": "KI",
"PRK": "KP",
"KOR": "KR",
"KWT": "KW",
"KGZ": "KG",
"LAO": "LA",
"LVA": "LV",
"LBN": "LB",
"LSO": "LS",
"LBR": "LR",
"LBY": "LY",
"LIE": "LI",
"LTU": "LT",
"LUX": "LU",
"MKD": "MK",
"MDG": "MG",
"MWI": "MW",
"MYS": "MY",
"MDV": "MV",
"MLI": "ML",
"MLT": "MT",
"MHL": "MH",
"MTQ": "MQ",
"MRT": "MR",
"MUS": "MU",
"MYT": "YT",
"MEX": "MX",
"FSM": "FM",
"MDA": "MD",
"MCO": "MC",
"MNG": "MN",
"MNE": "ME",
"MSR": "MS",
"MAR": "MA",
"MOZ": "MZ",
"MMR": "MM",
"NAM": "NA",
"NRU": "NR",
"NPL": "NP",
"NLD": "NL",
"ANT": "AN",
"NCL": "NC",
"NZL": "NZ",
"NIC": "NI",
"NER": "NE",
"NGA": "NG",
"NIU": "NU",
"NFK": "NF",
"MNP": "MP",
"NOR": "NO",
"OMN": "OM",
"PAK": "PK",
"PLW": "PW",
"PSE": "PS",
"PAN": "PA",
"PNG": "PG",
"PRY": "PY",
"PER": "PE",
"PHL": "PH",
"PCN": "PN",
"POL": "PL",
"PRT": "PT",
"PRI": "PR",
"QAT": "QA",
"REU": "RE",
"ROU": "RO",
"RUS": "RU",
"RWA": "RW",
"BLM": "BL",
"SHN": "SH",
"KNA": "KN",
"LCA": "LC",
"MAF": "MF",
"SPM": "PM",
"VCT": "VC",
"WSM": "WS",
"SMR": "SM",
"STP": "ST",
"SAU": "SA",
"SEN": "SN",
"SRB": "RS",
"SYC": "SC",
"SLE": "SL",
"SGP": "SG",
"SVK": "SK",
"SVN": "SI",
"SLB": "SB",
"SOM": "SO",
"ZAF": "ZA",
"SGS": "GS",
"SSD": "SS",
"ESP": "ES",
"LKA": "LK",
"SDN": "SD",
"SUR": "SR",
"SJM": "SJ",
"SWZ": "SZ",
"SWE": "SE",
"CHE": "CH",
"SYR": "SY",
"TWN": "TW",
"TJK": "TJ",
"TZA": "TZ",
"THA": "TH",
"TLS": "TL",
"TGO": "TG",
"TKL": "TK",
"TON": "TO",
"TTO": "TT",
"TUN": "TN",
"TUR": "TR",
"TKM": "TM",
"TCA": "TC",
"TUV": "TV",
"UGA": "UG",
"UKR": "UA",
"ARE": "AE",
"GBR": "GB",
"USA": "US",
"UMI": "UM",
"URY": "UY",
"UZB": "UZ",
"VUT": "VU",
"VEN": "VE",
"VNM": "VN",
"VIR": "VI",
"WLF": "WF",
"ESH": "EH",
"YEM": "YE",
"ZMB": "ZM",
"ZWE": "ZW",
"XKX": "XK",
}
def country_mapping(countrycode):
return countryISOMapping[countrycode]

@ -0,0 +1,20 @@
{
"author": [
"Bobloy"
],
"min_bot_version": "3.4.0",
"description": "Pull information from the Launch Library API for space flights",
"hidden": false,
"install_msg": "Thank you for installing LaunchLib. Get started with `[p]load launchlib`, then `[p]help LaunchLib`",
"short": "Access launch data for space flights",
"end_user_data_statement": "This cog does not store any End User Data",
"requirements": ["python-launch-library"],
"tags": [
"bobloy",
"utils",
"launch",
"space",
"api",
"library"
]
}

@ -0,0 +1,130 @@
import asyncio
import functools
import logging
import discord
import launchlibrary as ll
from redbot.core import Config, commands
from redbot.core.bot import Red
from launchlib.countrymapper import country_mapping
log = logging.getLogger("red.fox_v3.launchlib")
class LaunchLib(commands.Cog):
"""
Cog Description
Less important information about the cog
"""
def __init__(self, bot: Red):
super().__init__()
self.bot = bot
self.config = Config.get_conf(self, identifier=0, force_registration=True)
default_guild = {}
self.config.register_guild(**default_guild)
self.api = ll.Api()
async def red_delete_data_for_user(self, **kwargs):
"""Nothing to delete"""
return
async def _embed_launch_data(self, launch: ll.Launch):
status: ll.LaunchStatus = launch.get_status()
rocket: ll.Rocket = launch.rocket
title = launch.name
description = status.description
urls = launch.vid_urls + launch.info_urls
if not urls and rocket:
urls = rocket.info_urls + [rocket.wiki_url]
if urls:
url = urls[0]
else:
url = None
color = discord.Color.green() if status.id in [1, 3] else discord.Color.red()
em = discord.Embed(title=title, description=description, url=url, color=color)
if rocket and rocket.image_url and rocket.image_url != "Array":
em.set_image(url=rocket.image_url)
agency = getattr(launch, "agency", None)
if agency is not None:
em.set_author(
name=agency.name,
url=agency.wiki_url,
icon_url=f"https://www.countryflags.io/{country_mapping(agency.country_code)}/flat/64.png",
)
field_options = [
("failreason", "Fail Reason"),
("holdreason", "Hold Reason"),
("id", "ID"),
("hashtag", "Hashtag"),
]
for f in field_options:
data = getattr(launch, f[0], None)
if data is not None and data:
em.add_field(name=f[1], value=data)
if launch.missions:
field_options = [
("description", "Mission Description"),
("typeName", "Mission Type"),
("name", "Mission Name"),
]
for mission in launch.missions:
for f in field_options:
data = mission.get(f[0], None)
if data is not None and data:
em.add_field(name=f[1], value=data)
if rocket and rocket.family:
em.add_field(name="Rocket Family", value=rocket.family)
em.timestamp = launch.windowstart
em.set_footer()
return em
@commands.group()
async def launchlib(self, ctx: commands.Context):
if ctx.invoked_subcommand is None:
pass
@launchlib.command()
async def next(self, ctx: commands.Context, num_launches: int = 1):
# launches = await api.async_next_launches(num_launches)
loop = asyncio.get_running_loop()
launches = await loop.run_in_executor(
None, functools.partial(self.api.fetch_launch, num=num_launches)
)
# launches = self.api.fetch_launch(num=num_launches)
print(len(launches))
async with ctx.typing():
for x, launch in enumerate(launches):
if x >= num_launches:
return
em = await self._embed_launch_data(launch)
if em is not None:
try:
await ctx.send(embed=em)
except discord.HTTPException:
await ctx.send(str(launch))
log.exception("Failed to send embed")
await asyncio.sleep(2)

@ -4,7 +4,7 @@ from datetime import datetime, timedelta
import discord
from redbot.core import Config, checks, commands
from redbot.core.bot import Red
from redbot.core.commands import Cog
from redbot.core.commands import Cog, parse_timedelta
from redbot.core.utils.chat_formatting import pagify
@ -20,7 +20,7 @@ class Timerole(Cog):
self.config.register_global(**default_global)
self.config.register_guild(**default_guild)
self.updating = self.bot.loop.create_task(self.check_day())
self.updating = asyncio.create_task(self.check_day())
async def red_delete_data_for_user(self, **kwargs):
"""Nothing to delete"""
@ -40,7 +40,7 @@ class Timerole(Cog):
"""
await self.timerole_update()
await ctx.send("Success")
await ctx.tick()
@commands.group()
@checks.mod_or_permissions(administrator=True)
@ -52,23 +52,34 @@ class Timerole(Cog):
@timerole.command()
async def addrole(
self, ctx: commands.Context, role: discord.Role, days: int, *requiredroles: discord.Role
self, ctx: commands.Context, role: discord.Role, time: str, *requiredroles: discord.Role
):
"""Add a role to be added after specified time on server"""
guild = ctx.guild
to_set = {"days": days, "remove": False}
try:
parsed_time = parse_timedelta(time, allowed_units=["weeks", "days", "hours"])
except commands.BadArgument:
await ctx.maybe_send_embed("Error: Invalid time string.")
return
days = parsed_time.days
hours = parsed_time.seconds // 60 // 60
to_set = {"days": days, "hours": hours, "remove": False}
if requiredroles:
to_set["required"] = [r.id for r in requiredroles]
await self.config.guild(guild).roles.set_raw(role.id, value=to_set)
await ctx.maybe_send_embed(
"Time Role for {0} set to {1} days until added".format(role.name, days)
"Time Role for {0} set to {1} days and {2} hours until added".format(
role.name, days, hours
)
)
@timerole.command()
async def removerole(
self, ctx: commands.Context, role: discord.Role, days: int, *requiredroles: discord.Role
self, ctx: commands.Context, role: discord.Role, time: str, *requiredroles: discord.Role
):
"""
Add a role to be removed after specified time on server
@ -76,14 +87,24 @@ class Timerole(Cog):
Useful with an autorole cog
"""
guild = ctx.guild
try:
parsed_time = parse_timedelta(time, allowed_units=["weeks", "days", "hours"])
except commands.BadArgument:
await ctx.maybe_send_embed("Error: Invalid time string.")
return
to_set = {"days": days, "remove": True}
days = parsed_time.days
hours = parsed_time.seconds // 60 // 60
to_set = {"days": days, "hours": hours, "remove": True}
if requiredroles:
to_set["required"] = [r.id for r in requiredroles]
await self.config.guild(guild).roles.set_raw(role.id, value=to_set)
await ctx.maybe_send_embed(
"Time Role for {0} set to {1} days until removed".format(role.name, days)
"Time Role for {0} set to {1} days and {2} hours until removed".format(
role.name, days, hours
)
)
@timerole.command()
@ -174,7 +195,7 @@ class Timerole(Cog):
await member.add_roles(role, reason="Timerole")
else:
await member.remove_roles(role, reason="Timerole")
except discord.Forbidden:
except (discord.Forbidden, discord.NotFound) as e:
results += "{} : {} **(Failed)**\n".format(member.display_name, role.name)
else:
results += "{} : {}\n".format(member.display_name, role.name)
@ -192,7 +213,11 @@ class Timerole(Cog):
continue
if (
member.joined_at + timedelta(days=role_dict[str(role_id)]["days"])
member.joined_at
+ timedelta(
days=role_dict[str(role_id)]["days"],
hours=role_dict[str(role_id)].get("hours", 0),
)
<= datetime.today()
):
# Qualifies
@ -201,4 +226,4 @@ class Timerole(Cog):
async def check_day(self):
while self is self.bot.get_cog("Timerole"):
await self.timerole_update()
await asyncio.sleep(86400)
await asyncio.sleep(3600)

Loading…
Cancel
Save