diff --git a/.gitignore b/.gitignore index dadde2233..24380531a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,21 +6,7 @@ __pycache__/ *.so # Distribution / packaging -bin/ -build/ -develop-eggs/ -dist/ -eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -*.egg-info/ -.installed.cfg -*.egg .vscode/ .vs/ -meowth/config.py -docs/ -logs/ +meowth-logo.jpg +config/config.py diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..d66a5aaa2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,314 @@ +FROM python:3.10.13-slim-bookworm as s2geometry +LABEL maintainer="Jack Yaz " + + +### START S2GEOMETRY BUILD AND SETUP ### + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + build-essential \ + git \ + libgflags-dev \ + libgoogle-glog-dev \ + libgtest-dev \ + libssl-dev \ + swig \ + cmake \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN mkdir /app +RUN python3 -m venv /app/venv +ENV PATH="/app/venv/bin:$PATH" +RUN python3 -m pip install --upgrade pip + +WORKDIR /src +RUN git clone https://github.com/abseil/abseil-cpp --branch 20230802.1 +WORKDIR /src/abseil-cpp/build +RUN cmake -S /src/abseil-cpp -B /build/abseil-cpp -DCMAKE_INSTALL_PREFIX=/output -DABSL_BUILD_TESTING=OFF -DABSL_ENABLE_INSTALL=ON -DCMAKE_CXX_STANDARD=17 -DCMAKE_POSITION_INDEPENDENT_CODE=ON +RUN cmake --build /build/abseil-cpp --target install + +WORKDIR /src +RUN git clone https://github.com/google/s2geometry.git +WORKDIR /src/s2geometry/ +RUN cmake -DCMAKE_PREFIX_PATH=/output/lib/cmake/absl -DCMAKE_CXX_STANDARD=17 -DWITH_PYTHON=ON -DBUILD_TESTS=OFF +RUN make -j $(nproc) +RUN make install -j $(nproc) + +WORKDIR /src/s2geometry/ + +RUN sed -i "s/'-DWITH_PYTHON=ON'/'-DWITH_PYTHON=ON',/" /src/s2geometry/setup.py +RUN sed -i "/'-DWITH_PYTHON=ON',/a \ '-DCMAKE_PREFIX_PATH=/output/lib/cmake'" /src/s2geometry/setup.py +RUN sed -i "/'-DWITH_PYTHON=ON',/a \ '-DCMAKE_CXX_STANDARD=17'," /src/s2geometry/setup.py +RUN sed -i "/'-DWITH_PYTHON=ON',/a \ '-DBUILD_TESTS=OFF'," /src/s2geometry/setup.py +RUN sed -i 's/install_prefix="s2geometry"/install_prefix="pywraps2"/' /src/s2geometry/setup.py + +RUN python3 -m pip install cmake_build_extension wheel +RUN python3 setup.py bdist_wheel + +### END S2GEOMETRY BUILD AND SETUP ### + +### START POSTGRES BUILD AND SETUP ### + +FROM python:3.10.13-slim-bookworm as meowth +LABEL maintainer="Jack Yaz " + +# explicitly set user/group IDs +RUN set -eux; \ + groupadd -r postgres --gid=999; \ + # https://salsa.debian.org/postgresql/postgresql-common/blob/997d842ee744687d99a2b2d95c1083a2615c79e8/debian/postgresql-common.postinst#L32-35 + useradd -r -g postgres --uid=999 --home-dir=/var/lib/postgresql --shell=/bin/bash postgres; \ + # also create the postgres user's home directory with appropriate permissions + # see https://github.com/docker-library/postgres/issues/274 + mkdir -p /var/lib/postgresql; \ + chown -R postgres:postgres /var/lib/postgresql + +RUN set -ex; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + gnupg \ + ; \ + rm -rf /var/lib/apt/lists/* + +# grab gosu for easy step-down from root +# https://github.com/tianon/gosu/releases +ENV GOSU_VERSION 1.17 +RUN set -eux; \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends ca-certificates wget; \ + rm -rf /var/lib/apt/lists/*; \ + dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ + apt-mark auto '.*' > /dev/null; \ + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + chmod +x /usr/local/bin/gosu; \ + gosu --version; \ + gosu nobody true + +# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default +RUN set -eux; \ + if [ -f /etc/dpkg/dpkg.cfg.d/docker ]; then \ + # if this file exists, we're likely in "debian:xxx-slim", and locales are thus being excluded so we need to remove that exclusion (since we need locales) + grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ + sed -ri '/\/usr\/share\/locale/d' /etc/dpkg/dpkg.cfg.d/docker; \ + ! grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ + fi; \ + apt-get update; apt-get install -y --no-install-recommends locales; rm -rf /var/lib/apt/lists/*; \ + localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 +ENV LANG en_US.utf8 + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + libnss-wrapper \ + xz-utils \ + zstd \ + ; \ + rm -rf /var/lib/apt/lists/* + +RUN mkdir /docker-entrypoint-initdb.d + +RUN set -ex; \ + # pub 4096R/ACCC4CF8 2011-10-13 [expires: 2019-07-02] + # Key fingerprint = B97B 0AFC AA1A 47F0 44F2 44A0 7FCC 7D46 ACCC 4CF8 + # uid PostgreSQL Debian Repository + key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ + export GNUPGHOME="$(mktemp -d)"; \ + mkdir -p /usr/local/share/keyrings/; \ + gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \ + gpg --batch --export --armor "$key" > /usr/local/share/keyrings/postgres.gpg.asc; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME" + +ENV PG_MAJOR 15 +ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin + +ENV PG_VERSION 15.6-1.pgdg120+2 + +RUN set -ex; \ + \ + # see note below about "*.pyc" files + export PYTHONDONTWRITEBYTECODE=1; \ + \ + dpkgArch="$(dpkg --print-architecture)"; \ + aptRepo="[ signed-by=/usr/local/share/keyrings/postgres.gpg.asc ] http://apt.postgresql.org/pub/repos/apt/ bookworm-pgdg main $PG_MAJOR"; \ + case "$dpkgArch" in \ + amd64 | arm64 | ppc64el | s390x) \ + # arches officialy built by upstream + echo "deb $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ + apt-get update; \ + ;; \ + *) \ + # we're on an architecture upstream doesn't officially build for + # let's build binaries from their published source packages + echo "deb-src $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + \ + tempDir="$(mktemp -d)"; \ + cd "$tempDir"; \ + \ + # create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) + apt-get update; \ + apt-get install -y --no-install-recommends dpkg-dev; \ + echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list; \ + _update_repo() { \ + dpkg-scanpackages . > Packages; \ + # work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") + # Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) + # ... + # E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) + apt-get -o Acquire::GzipIndexes=false update; \ + }; \ + _update_repo; \ + \ + # build .deb files from upstream's source packages (which are verified by apt-get) + nproc="$(nproc)"; \ + export DEB_BUILD_OPTIONS="nocheck parallel=$nproc"; \ + # we have to build postgresql-common first because postgresql-$PG_MAJOR shares "debian/rules" logic with it: https://salsa.debian.org/postgresql/postgresql/-/commit/99f44476e258cae6bf9e919219fa2c5414fa2876 + # (and it "Depends: pgdg-keyring") + apt-get build-dep -y postgresql-common pgdg-keyring; \ + apt-get source --compile postgresql-common pgdg-keyring; \ + _update_repo; \ + apt-get build-dep -y "postgresql-$PG_MAJOR=$PG_VERSION"; \ + apt-get source --compile "postgresql-$PG_MAJOR=$PG_VERSION"; \ + \ + # we don't remove APT lists here because they get re-downloaded and removed later + \ + # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies + # (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) + apt-mark showmanual | xargs apt-mark auto > /dev/null; \ + apt-mark manual $savedAptMark; \ + \ + ls -lAFh; \ + _update_repo; \ + grep '^Package: ' Packages; \ + cd /; \ + ;; \ + esac; \ + \ + apt-get install -y --no-install-recommends postgresql-common; \ + sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf; \ + apt-get install -y --no-install-recommends \ + "postgresql-$PG_MAJOR=$PG_VERSION" \ + ; \ + \ + rm -rf /var/lib/apt/lists/*; \ + \ + if [ -n "$tempDir" ]; then \ + # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) + apt-get purge -y --auto-remove; \ + rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ + fi; \ + \ + # some of the steps above generate a lot of "*.pyc" files (and setting "PYTHONDONTWRITEBYTECODE" beforehand doesn't propagate properly for some reason), so we clean them up manually (as long as they aren't owned by a package) + find /usr -name '*.pyc' -type f -exec bash -c 'for pyc; do dpkg -S "$pyc" &> /dev/null || rm -vf "$pyc"; done' -- '{}' +; \ + \ + postgres --version + +# make the sample config easier to munge (and "correct by default") +RUN set -eux; \ + dpkg-divert --add --rename --divert "/usr/share/postgresql/postgresql.conf.sample.dpkg" "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample"; \ + cp -v /usr/share/postgresql/postgresql.conf.sample.dpkg /usr/share/postgresql/postgresql.conf.sample; \ + ln -sv ../postgresql.conf.sample "/usr/share/postgresql/$PG_MAJOR/"; \ + sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample; \ + grep -F "listen_addresses = '*'" /usr/share/postgresql/postgresql.conf.sample + +RUN mkdir -p /var/run/postgresql && chown -R postgres:postgres /var/run/postgresql && chmod 2777 /var/run/postgresql + +ENV PGDATA /var/lib/postgresql/data +# this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values) +RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" + +# We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL +# calls "Fast Shutdown mode" wherein new connections are disallowed and any +# in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and +# flush tables to disk, which is the best compromise available to avoid data +# corruption. +# +# Users who know their applications do not keep open long-lived idle connections +# may way to use a value of SIGTERM instead, which corresponds to "Smart +# Shutdown mode" in which any existing sessions are allowed to finish and the +# server stops when all sessions are terminated. +# +# See https://www.postgresql.org/docs/12/server-shutdown.html for more details +# about available PostgreSQL server shutdown signals. +# +# See also https://www.postgresql.org/docs/12/server-start.html for further +# justification of this as the default value, namely that the example (and +# shipped) systemd service files use the "Fast Shutdown mode" for service +# termination. +# +STOPSIGNAL SIGINT +# +# An additional setting that is recommended for all users regardless of this +# value is the runtime "--stop-timeout" (or your orchestrator/runtime's +# equivalent) for controlling how long to wait between sending the defined +# STOPSIGNAL and sending SIGKILL (which is likely to cause data corruption). +# +# The default in most runtimes (such as Docker) is 10 seconds, and the +# documentation at https://www.postgresql.org/docs/12/server-start.html notes +# that even 90 seconds may not be long enough in many instances. + +### END POSTGRES BUILD AND SETUP ### + +### START MEOWTH BUILD AND SETUP ### + +RUN mkdir /app +COPY --from=s2geometry /src/s2geometry/dist/*.whl /app/. + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + git \ + sudo \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN echo 'postgres ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +RUN python3 -m venv /app/venv +ENV PATH="/app/venv/bin:$PATH" +RUN python3 -m pip install --upgrade pip + +RUN python3 -m pip install /app/*.whl + +COPY config /app/config +COPY database /app/database +COPY meowth /app/meowth +COPY requirements.txt /app/ +COPY setup.py /app/ +COPY README.md /app/ +COPY LICENSE /app/ + +WORKDIR /app + +RUN python3 -m pip install -r requirements.txt +RUN python3 setup.py install + +RUN ln -s /app/config/config.py /app/meowth/config.py + +WORKDIR / + +### END MEOWTH BUILD AND SETUP ### + +ENV PYTHONPATH="/app" + +COPY entry.sh / +RUN chmod 0755 /entry.sh + +VOLUME /app/config +VOLUME /var/lib/postgresql/data + +EXPOSE 5432 + +ENTRYPOINT ["/entry.sh"] + +CMD ["postgres"] diff --git a/Dockerfile-arm64 b/Dockerfile-arm64 new file mode 100644 index 000000000..abf46322e --- /dev/null +++ b/Dockerfile-arm64 @@ -0,0 +1,314 @@ +FROM python:3.10.13-slim-bookworm as s2geometry +LABEL maintainer="Jack Yaz " + + +### START S2GEOMETRY BUILD AND SETUP ### + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + build-essential \ + git \ + libgflags-dev \ + libgoogle-glog-dev \ + libgtest-dev \ + libssl-dev \ + swig \ + cmake \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN mkdir /app +RUN python3 -m venv /app/venv +ENV PATH="/app/venv/bin:$PATH" +RUN python3 -m pip install --upgrade pip + +WORKDIR /src +RUN git clone https://github.com/abseil/abseil-cpp --branch 20230802.1 +WORKDIR /src/abseil-cpp/build +RUN cmake -S /src/abseil-cpp -B /build/abseil-cpp -DCMAKE_INSTALL_PREFIX=/output -DABSL_BUILD_TESTING=OFF -DABSL_ENABLE_INSTALL=ON -DCMAKE_CXX_STANDARD=17 -DCMAKE_POSITION_INDEPENDENT_CODE=ON +RUN cmake --build /build/abseil-cpp --target install + +WORKDIR /src +RUN git clone https://github.com/google/s2geometry.git +WORKDIR /src/s2geometry/ +RUN cmake -DCMAKE_PREFIX_PATH=/output/lib/cmake/absl -DCMAKE_CXX_STANDARD=17 -DWITH_PYTHON=ON -DBUILD_TESTS=OFF +RUN make -j $(nproc) +RUN make install -j $(nproc) + +WORKDIR /src/s2geometry/ + +RUN sed -i "s/'-DWITH_PYTHON=ON'/'-DWITH_PYTHON=ON',/" /src/s2geometry/setup.py +RUN sed -i "/'-DWITH_PYTHON=ON',/a \ '-DCMAKE_PREFIX_PATH=/output/lib/cmake'" /src/s2geometry/setup.py +RUN sed -i "/'-DWITH_PYTHON=ON',/a \ '-DCMAKE_CXX_STANDARD=17'," /src/s2geometry/setup.py +RUN sed -i "/'-DWITH_PYTHON=ON',/a \ '-DBUILD_TESTS=OFF'," /src/s2geometry/setup.py +RUN sed -i 's/install_prefix="s2geometry"/install_prefix="pywraps2"/' /src/s2geometry/setup.py + +RUN python3 -m pip install cmake_build_extension wheel +RUN python3 setup.py bdist_wheel + +### END S2GEOMETRY BUILD AND SETUP ### + +### START POSTGRES BUILD AND SETUP ### + +FROM python:3.10.13-bookworm as meowth +LABEL maintainer="Jack Yaz " + +# explicitly set user/group IDs +RUN set -eux; \ + groupadd -r postgres --gid=999; \ + # https://salsa.debian.org/postgresql/postgresql-common/blob/997d842ee744687d99a2b2d95c1083a2615c79e8/debian/postgresql-common.postinst#L32-35 + useradd -r -g postgres --uid=999 --home-dir=/var/lib/postgresql --shell=/bin/bash postgres; \ + # also create the postgres user's home directory with appropriate permissions + # see https://github.com/docker-library/postgres/issues/274 + mkdir -p /var/lib/postgresql; \ + chown -R postgres:postgres /var/lib/postgresql + +RUN set -ex; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + gnupg \ + ; \ + rm -rf /var/lib/apt/lists/* + +# grab gosu for easy step-down from root +# https://github.com/tianon/gosu/releases +ENV GOSU_VERSION 1.16 +RUN set -eux; \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends ca-certificates wget; \ + rm -rf /var/lib/apt/lists/*; \ + dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ + apt-mark auto '.*' > /dev/null; \ + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + chmod +x /usr/local/bin/gosu; \ + gosu --version; \ + gosu nobody true + +# make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default +RUN set -eux; \ + if [ -f /etc/dpkg/dpkg.cfg.d/docker ]; then \ + # if this file exists, we're likely in "debian:xxx-slim", and locales are thus being excluded so we need to remove that exclusion (since we need locales) + grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ + sed -ri '/\/usr\/share\/locale/d' /etc/dpkg/dpkg.cfg.d/docker; \ + ! grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ + fi; \ + apt-get update; apt-get install -y --no-install-recommends locales; rm -rf /var/lib/apt/lists/*; \ + localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 +ENV LANG en_US.utf8 + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + libnss-wrapper \ + xz-utils \ + zstd \ + ; \ + rm -rf /var/lib/apt/lists/* + +RUN mkdir /docker-entrypoint-initdb.d + +RUN set -ex; \ + # pub 4096R/ACCC4CF8 2011-10-13 [expires: 2019-07-02] + # Key fingerprint = B97B 0AFC AA1A 47F0 44F2 44A0 7FCC 7D46 ACCC 4CF8 + # uid PostgreSQL Debian Repository + key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ + export GNUPGHOME="$(mktemp -d)"; \ + mkdir -p /usr/local/share/keyrings/; \ + gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \ + gpg --batch --export --armor "$key" > /usr/local/share/keyrings/postgres.gpg.asc; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME" + +ENV PG_MAJOR 15 +ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin + +ENV PG_VERSION 15.5-1.pgdg120+1 + +RUN set -ex; \ + \ + # see note below about "*.pyc" files + export PYTHONDONTWRITEBYTECODE=1; \ + \ + dpkgArch="$(dpkg --print-architecture)"; \ + aptRepo="[ signed-by=/usr/local/share/keyrings/postgres.gpg.asc ] http://apt.postgresql.org/pub/repos/apt/ bookworm-pgdg main $PG_MAJOR"; \ + case "$dpkgArch" in \ + amd64 | arm64 | ppc64el | s390x) \ + # arches officialy built by upstream + echo "deb $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ + apt-get update; \ + ;; \ + *) \ + # we're on an architecture upstream doesn't officially build for + # let's build binaries from their published source packages + echo "deb-src $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + \ + tempDir="$(mktemp -d)"; \ + cd "$tempDir"; \ + \ + # create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) + apt-get update; \ + apt-get install -y --no-install-recommends dpkg-dev; \ + echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list; \ + _update_repo() { \ + dpkg-scanpackages . > Packages; \ + # work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") + # Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) + # ... + # E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) + apt-get -o Acquire::GzipIndexes=false update; \ + }; \ + _update_repo; \ + \ + # build .deb files from upstream's source packages (which are verified by apt-get) + nproc="$(nproc)"; \ + export DEB_BUILD_OPTIONS="nocheck parallel=$nproc"; \ + # we have to build postgresql-common first because postgresql-$PG_MAJOR shares "debian/rules" logic with it: https://salsa.debian.org/postgresql/postgresql/-/commit/99f44476e258cae6bf9e919219fa2c5414fa2876 + # (and it "Depends: pgdg-keyring") + apt-get build-dep -y postgresql-common pgdg-keyring; \ + apt-get source --compile postgresql-common pgdg-keyring; \ + _update_repo; \ + apt-get build-dep -y "postgresql-$PG_MAJOR=$PG_VERSION"; \ + apt-get source --compile "postgresql-$PG_MAJOR=$PG_VERSION"; \ + \ + # we don't remove APT lists here because they get re-downloaded and removed later + \ + # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies + # (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) + apt-mark showmanual | xargs apt-mark auto > /dev/null; \ + apt-mark manual $savedAptMark; \ + \ + ls -lAFh; \ + _update_repo; \ + grep '^Package: ' Packages; \ + cd /; \ + ;; \ + esac; \ + \ + apt-get install -y --no-install-recommends postgresql-common; \ + sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf; \ + apt-get install -y --no-install-recommends \ + "postgresql-$PG_MAJOR=$PG_VERSION" \ + ; \ + \ + rm -rf /var/lib/apt/lists/*; \ + \ + if [ -n "$tempDir" ]; then \ + # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) + apt-get purge -y --auto-remove; \ + rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ + fi; \ + \ + # some of the steps above generate a lot of "*.pyc" files (and setting "PYTHONDONTWRITEBYTECODE" beforehand doesn't propagate properly for some reason), so we clean them up manually (as long as they aren't owned by a package) + find /usr -name '*.pyc' -type f -exec bash -c 'for pyc; do dpkg -S "$pyc" &> /dev/null || rm -vf "$pyc"; done' -- '{}' +; \ + \ + postgres --version + +# make the sample config easier to munge (and "correct by default") +RUN set -eux; \ + dpkg-divert --add --rename --divert "/usr/share/postgresql/postgresql.conf.sample.dpkg" "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample"; \ + cp -v /usr/share/postgresql/postgresql.conf.sample.dpkg /usr/share/postgresql/postgresql.conf.sample; \ + ln -sv ../postgresql.conf.sample "/usr/share/postgresql/$PG_MAJOR/"; \ + sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample; \ + grep -F "listen_addresses = '*'" /usr/share/postgresql/postgresql.conf.sample + +RUN mkdir -p /var/run/postgresql && chown -R postgres:postgres /var/run/postgresql && chmod 2777 /var/run/postgresql + +ENV PGDATA /var/lib/postgresql/data +# this 777 will be replaced by 700 at runtime (allows semi-arbitrary "--user" values) +RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 777 "$PGDATA" + +# We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL +# calls "Fast Shutdown mode" wherein new connections are disallowed and any +# in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and +# flush tables to disk, which is the best compromise available to avoid data +# corruption. +# +# Users who know their applications do not keep open long-lived idle connections +# may way to use a value of SIGTERM instead, which corresponds to "Smart +# Shutdown mode" in which any existing sessions are allowed to finish and the +# server stops when all sessions are terminated. +# +# See https://www.postgresql.org/docs/12/server-shutdown.html for more details +# about available PostgreSQL server shutdown signals. +# +# See also https://www.postgresql.org/docs/12/server-start.html for further +# justification of this as the default value, namely that the example (and +# shipped) systemd service files use the "Fast Shutdown mode" for service +# termination. +# +STOPSIGNAL SIGINT +# +# An additional setting that is recommended for all users regardless of this +# value is the runtime "--stop-timeout" (or your orchestrator/runtime's +# equivalent) for controlling how long to wait between sending the defined +# STOPSIGNAL and sending SIGKILL (which is likely to cause data corruption). +# +# The default in most runtimes (such as Docker) is 10 seconds, and the +# documentation at https://www.postgresql.org/docs/12/server-start.html notes +# that even 90 seconds may not be long enough in many instances. + +### END POSTGRES BUILD AND SETUP ### + +### START MEOWTH BUILD AND SETUP ### + +RUN mkdir /app +COPY --from=s2geometry /src/s2geometry/dist/*.whl /app/. + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + git \ + sudo \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN echo 'postgres ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + +RUN python3 -m venv /app/venv +ENV PATH="/app/venv/bin:$PATH" +RUN python3 -m pip install --upgrade pip + +RUN python3 -m pip install /app/*.whl + +COPY config /app/config +COPY database /app/database +COPY meowth /app/meowth +COPY requirements.txt /app/ +COPY setup.py /app/ +COPY README.md /app/ +COPY LICENSE /app/ + +WORKDIR /app + +RUN python3 -m pip install -r requirements.txt +RUN python3 setup.py install + +RUN ln -s /app/config/config.py /app/meowth/config.py + +WORKDIR / + +### END MEOWTH BUILD AND SETUP ### + +ENV PYTHONPATH="/app" + +COPY entry.sh / +RUN chmod 0755 /entry.sh + +VOLUME /app/config +VOLUME /var/lib/postgresql/data + +EXPOSE 5432 + +ENTRYPOINT ["/entry.sh"] + +CMD ["postgres"] diff --git a/Dockerfile-nopsql b/Dockerfile-nopsql new file mode 100644 index 000000000..a2e611444 --- /dev/null +++ b/Dockerfile-nopsql @@ -0,0 +1,101 @@ +FROM python:3.10.13-slim-bookworm as s2geometry +LABEL maintainer="Jack Yaz " + + +### START S2GEOMETRY BUILD AND SETUP ### + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + build-essential \ + git \ + libgflags-dev \ + libgoogle-glog-dev \ + libgtest-dev \ + libssl-dev \ + swig \ + cmake \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN mkdir /app +RUN python3 -m venv /app/venv +ENV PATH="/app/venv/bin:$PATH" +RUN python3 -m pip install --upgrade pip + +WORKDIR /src +RUN git clone https://github.com/google/googletest +RUN cmake -S /src/googletest -B /build/googletest -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/output -DBUILD_GMOCK=ON +RUN cmake --build /build/googletest --target install + +WORKDIR /src +RUN git clone https://github.com/abseil/abseil-cpp +WORKDIR /src/abseil-cpp/build +RUN cmake -S /src/abseil-cpp -B /build/abseil-cpp -DCMAKE_PREFIX_PATH=/output -DCMAKE_INSTALL_PREFIX=/output -DABSL_ENABLE_INSTALL=ON -DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON -DCMAKE_CXX_STANDARD=17 -DCMAKE_POSITION_INDEPENDENT_CODE=ON +RUN cmake --build /build/abseil-cpp --target install + +WORKDIR /src +RUN git clone https://github.com/google/s2geometry.git +WORKDIR /src/s2geometry/ +RUN cmake -DCMAKE_PREFIX_PATH=/output/lib/cmake/absl -DCMAKE_CXX_STANDARD=17 -DWITH_PYTHON=ON +RUN make -j $(nproc) +RUN make install -j $(nproc) + +WORKDIR /src/s2geometry/ + +RUN sed -i "s/'-DWITH_PYTHON=ON'/'-DWITH_PYTHON=ON',/" /src/s2geometry/setup.py +RUN sed -i "/'-DWITH_PYTHON=ON',/a \ '-DCMAKE_PREFIX_PATH=/output/lib/cmake'" /src/s2geometry/setup.py +RUN sed -i "/'-DWITH_PYTHON=ON',/a \ '-DCMAKE_CXX_STANDARD=17'," /src/s2geometry/setup.py +RUN sed -i 's/install_prefix="s2geometry"/install_prefix="pywraps2"/' /src/s2geometry/setup.py + +RUN python3 -m pip install cmake_build_extension wheel +RUN python3 setup.py bdist_wheel + +### END S2GEOMETRY BUILD AND SETUP ### + +### START MEOWTH BUILD AND SETUP ### + +FROM python:3.10.13-slim-bookworm as meowth +LABEL maintainer="Jack Yaz " + +RUN mkdir /app +COPY --from=s2geometry /src/s2geometry/dist/s2geometry-0.11.0.dev1-cp310-cp310-linux_x86_64.whl /app/s2geometry-0.11.0.dev1-cp310-cp310-linux_x86_64.whl + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + git \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN python3 -m venv /app/venv +ENV PATH="/app/venv/bin:$PATH" +RUN python3 -m pip install --upgrade pip + +RUN python3 -m pip install /app/*.whl + +COPY config /app/config +COPY database /app/database +COPY meowth /app/meowth +COPY requirements.txt /app/ +COPY setup.py /app/ +COPY README.md /app/ +COPY LICENSE /app/ + +WORKDIR /app + +RUN python3 -m pip install -r requirements.txt +RUN python3 setup.py install + +RUN ln -s /app/config/config.py /app/meowth/config.py + +WORKDIR / + +### END MEOWTH BUILD AND SETUP ### + +ENV PYTHONPATH="/app" + +COPY entry-nopsql.sh / +RUN chmod 0755 /entry-nopsql.sh + +VOLUME /app/config + +ENTRYPOINT ["/entry-nopsql.sh"] diff --git a/README.md b/README.md index fb070e83c..d46166667 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,3 @@ -[![PyPI](https://img.shields.io/badge/discord.py-1.0.0a-green.svg)](https://github.com/Rapptz/discord.py/) -[![PyPI](https://img.shields.io/badge/python-3.6-blue.svg)](https://www.python.org/downloads/release/python-364/) -[![PyPI](https://img.shields.io/badge/support-discord-lightgrey.svg)](https://discord.gg/hhVjAN8) - # Meowth A Discord helper bot for Pokemon Go communities. @@ -21,7 +17,6 @@ Meowth assists with organising Pokemon Go communities with support for: #### *`Note: All reports are provided by your active server members. Meowth does not support any TOS breaking features such as spoofing, Pokemon Go bot accounts and automated raid reporting.`* - You can join the Meowth Discord Support Server for setup help: https://discord.gg/hhVjAN8 @@ -29,112 +24,77 @@ https://discord.gg/hhVjAN8 ## Dependencies -## **`Python 3.8+`** - -[Go here](https://github.com/FoglyOgly/Meowth#installing-python) for details on how to install Python 3.6. +## Docker -**For all future CLI commands, replace the command name `python3` with the relevant interpreter command name for your system (such as the common `py` command name on Windows). See details [here](https://github.com/FoglyOgly/Meowth#installing-python).** +### Installing Docker -## **`Other dependencies`** +[Go here](https://docs.docker.com/engine/install/) for details on how to install Docker. -Note: It is recommended to setup a venv for this as newer versions of some dependencies may have breaking changes. +### Usage +A Docker image for this app is available on [Docker Hub](https://hub.docker.com/r/jackyaz/meowth) +#### docker cli ```bash -python3 -m pip install -r requirements.txt +docker run -d \ + --name=meowth \ + -v /path/to/data:/app/config \ + --restart unless-stopped \ + jackyaz.io/jackyaz/meowth ``` -## **`S2Geometry`** +#### Parameters +The Docker image supports some parameters. These parameters are separated by a colon and indicate `:` respectively. For example, `-v /apps/meowth:/app/config` would map ```/apps/meowth``` on the Docker host to ```/app/config``` inside the container, allowing you to edit the configuration file from outside the container. -The Meowth mapping extension, which is responsible for storing location information on gyms, pokestops, etc., as well as for defining the geographical areas covered by reporting channels, the weather forecasting features, etc, is all based on the S2Geometry framework. This is a C++ package that has a Python wrapper that can be very very difficult to get working. Since the last time it was set up things seem to have changed quite a bit, so you will need to visit the [S2Geometry](https://s2geometry.io/) website to try to get it working with your Python installation. +| Parameter | Function | +| :----: | --- | +| `-v /app/config` | Local path for Meowth configuration directory | -## **`Meowth`** +## Running Meowth 1. Create a Bot user in the [Discord Developers panel](https://discordapp.com/developers/applications/me): - - Click `New App` - - Add an App Name, Description and App Icon (which will be intial bot avatar image) - - Click `Create App` - - Click `Create a Bot User` - - Copy down your Client ID in the App Details box at the very top - - In the App Bot User box, click to reveal Token and copy it down + - Click `New Application` + - Add an App Name and click Create + - Make a note of your Application ID + - Click `Bot` + - Enable the Privileged Gateway Intents and click Save Changes + - Click Reset Token and then make a note of the generated Token - *Optional:* Tick the Public Bot tickbox if you want to allow others to invite your bot to their own server. -1. Download the files in this repository, or your own fork if you intend to modify source - #### *``Note: If you alter the code significantly, adapt to support platforms we don't or integrate any TOS-breaking features, we ask you don't name your instance Meowth to avoid confusion to users between our instance and yours.``* - -1. Copy the bot config template `config_blank.json`, rename to `config.json` and edit it: +1. Copy the bot config template `config_template.py`, rename to `config.py` and edit it: - `bot_token` is the Token you copied down earlier from the Discord Developers page and requires quotes as it's a string. - `default_prefix` is the prefix the bot will use by default until a guild specifies otherwise with the `set prefix` command - - `master` is your personal discord account ID. This should be a long set of numbers like `174764205927432192` and should not have quotes around it, as it's an `int` not a string. + - `bot_master` is your personal discord account ID. This should be a long set of numbers like `174764205927432192` and should not have quotes around it, as it's an `int` not a string. * You can get your ID by enabling Developer Mode on the Discord Client, in `User Settings` > `Appearance` > `Advanced`, which then enables you to right-click your username in chat and select the option `Copy ID` * Another method is to mention yourself in chat and add `\` directly behind the mention for it to escape the mention string that's created, revealing your ID. - - `type_id_dict` specifies what Pokemon Type emojis to use for your bot. + - `xyz_emoji` specifies which emojis to use for your bot. - By default, it assumes you have the emojis in your own discord guild, and doesn't use the specific external emoji format. If you intend to allow the bot on multiple guilds, you will want to setup the external emoji strings. 1. Invite your Bot's User to your guild: - - Get the Client ID you copied earlier from the Discord Developers page and replace the text `` with it in the following URL: - `https://discordapp.com/oauth2/authorize?client_id=&scope=bot&permissions=268822608` + - Get the Application ID you copied earlier from the Discord Developers page and replace the text `` with it in the following URL: + `https://discordapp.com/oauth2/authorize?client_id=&scope=bot&permissions=18135768366161` - Go to the URL, select your server and click `Authorize` - Verify you aren't a robot (if the captcha doesn't appear, disable your adblocker) - - - -1. Run the launcher from the command prompt or terminal window: - `python3 launcher.py` - If successful, it should send "Meowth! That's right!" as well as basic info on startup. +1. Start the Docker container. You can check everything is up and running by checking the container logs (e.g. ```sudo docker logs -f meowth```) and looking for output similar to the below: + ``` + Launching... Connected. + Shard 0 is ready. + We're on! + + Bot Version: 3 + + Python Version: 3.10.13 + Discord.py Version: 2.0.0a3786+g3d74da8d + Platform: Linux-5.15.90.1-microsoft-standard-WSL2-x86_64-with-glibc2.36 + + Servers: 1 + Members: 1 + + Invite URL: https://discord.com/oauth2/authorize?client_id=1234567890&scope=bot&permissions=18135768366161 + ``` 1. Simply type `!configure` in your server to start the configuration process as normal. -## Launcher Reference: -### Arguments -``` - --help, -h Show the help message - --auto-restart, -r Auto-Restarts Meowth in case of a crash. - --debug, -d Prevents output being sent to Discord DM, as restarting - could occur often. -``` - -### Launch Meowth normally -```bash -python3 launcher.py -``` - -### Launch Meowth in debug mode if working on code changes -```bash -python3 launcher.py -d -``` - -### Launch Meowth with Auto-Restart -```bash -python3 launcher.py -r -``` - -## How to Translate Meowth: - -We currently only support English with our public bot, with self-hosting being the only way to support other languages. - -However, we have quite a few people [on our support server](https://discord.gg/hhVjAN8) who have been working on their own translations in a variety of languages. - -If you are wanting to translate Meowth to your language, check there in our `#non-english-support` channel to see if someone might be able to share what they've worked on in the language you need. - -To translate Meowth yourself, you can use pygettext.py and edit the generated translation files using [Poedit](https://poedit.net/). - -To generate a .pot file in Windows for example: - -1. Nativate to `[pythonpath]\Python36\Tools\i18n\` - -1. Open Command Prompt or PowerShell in this directory and run: - - `py pygettext.py -d ` - -1. This will generate a meowth.pot that you can then translate using Poedit - -1. Place the po/mo files from poedit into the `/locale//LC_MESSAGES` directory (use other languages for reference) - -1. Change Meowth's config.json `bot-language` and `pokemon-language` to `` - -#### *``Note: Since moving to Python 3.6 we have utlised f-strings in our source code in order to take advantage of the cleanliness and additional performance it brings. Unfortunately, we have later found out it is incompatible with pygettext's string extraction and replacement methods. As such, any strings that require translating that use f-strings will need to be edited in source to use str.format() instead.``* - ## Directions for using Meowth: Note: Avoid punctuation inside commands. @@ -148,56 +108,30 @@ Meowth relies completely on users for reports. Meowth was designed as an alterna If you are having trouble getting Meowth running in your server, we have found that the majority of problems are either from permissions or your configuration. Check permissions with `!get perms` and check your configuration with `!configure` before asking for help in the support server. -## Known issues: - -Compatibility with Python 3.6 on Mac OS X requires running "Install Certificates.command" in the Python 3.6 folder. - -# Installing Python - -## Windows +# Database Setup -Install the latest Python 3.6 package from the official site if you have not already got it. At the time of writing, Python 3.6.5 was the latest maintenance release. -https://www.python.org/downloads/release/python-365/ +Meowth uses a Postgres database for data management. -Python must be added the the environment's PATH, which is typically done automatically on install. +## Using the Docker container's built-in Postgres database -Your newly installed Python interpreter can be run in CLI in either Command Prompt or PowerShell typically with one of the following commands: +The Docker container includes Postgres with a pre-configured database ready for use, no extra steps are required. -> `python` -> `py` -> `py -3` -> `py -3.6` +## Using a separate Postgres database -To check your referenced interpreter version, use: -```bash -python --version -``` +### Loading the required data -Be sure to replace all instructions that specify a certain interpreter command with the one relevant to your system, as this differs between each individual OS, configuration and environment. +The schema and required data are provided in the database directory. Using either the pgAdmin app or the psql command-line tool, load the files in the database directory starting with the schema. -#### Linux +The schema contains the information on all the required tables as well as the triggers and functions that enable some real-time updates to trigger Meowth messages. -If you're using Linux, you will likely have a version of Python 3 already installed on your system. Check your current version with: -```bash -python3 --version -``` +Once the schema is loaded, each remaining file in the directory contains required data for another table. These are critical data regarding Pokemon, their moves, and so on. However, the data in them is badly out of date in some respects. You will likely have to do a lot of manual work here to get things up to date - for instance, many Pokemon which were not available in the wild at the time of the last update to the data are now available in the wild. You will either need to make a blanket update to allow all Pokemon to be reported in the wild or you will need to figure out which ones are missing. -If the version is not `3.8` or above, or `python3` is not found, you will need to install it on your system. You do not need to remove any existing versions from your system and it is usually not recommended to uninstal the default package as other system packages may rely on it. +Instructions on how to update the data in the database likely requires some basic knowledge of SQL and is beyond the scope of this readme. -# Database Setup +### Configuring Meowth -## Installing PostgreSQL - -Meowth uses a Postgres database for data management. The schema and required data are provided in the database directory. You should make sure that postgres is installed on the machine you intend to run Meowth on as Meowth uses a purely local connection to the database. Visit the [Postgres website](https://www.postgresql.org/) to download Postgres if necessary. When installed, create a database called meowth on the server. - -## Loading the required data - -Using either the pgAdmin app or the psql command-line tool, load the files in the database directory starting with the schema. The schema contains the information on all the required tables as well as the triggers and functions that enable some real-time updates to trigger Meowth messages. Once the schema is loaded, each remaining file in the directory contains required data for another table. These are critical data regarding Pokemon, their moves, and so on. However, the data in them is badly out of date in some respects. You will likely have to do a lot of manual work here to get things up to date - for instance, many Pokemon which were not available in the wild at the time of the last update to the data are now available in the wild. You will either need to make a blanket update to allow all Pokemon to be reported in the wild or you will need to figure out which ones are missing. Instructions on how to update the data in the database likely requires some basic knowledge of SQL and is beyond the scope of this readme. +Modify the relevant settings in config.py in the db_details section. ## Keeping the database up to date Several Meowth features, notably the raid feature, require Meowth to have an up-to-date list of the available raid bosses in the raid_bosses table. In the past, this data was available via a Silph Road API. At the time of this writing there is no known alternative API, so updates must be done to the database manually. Additionally, as new Pokemon, forms, variants, moves, etc. become available in the game, various tables need to be kept up-to-date manually as well. - -# Running Meowth locally - -When Meowth began, it was a purely local effort run for one Discord server out of its creator's parent's house on a seldom-used iMac. In this configuration the only requirement to run Meowth for a single server or a small number of servers is to run it on a machine that can stay on and connected to the Internet most of the time. If that isn't doable, there are various cloud hosting services such as AWS, Azure, and GCP, along with others. Many of these offer free trials or some limited services for free indefinitely, but it definitely adds complexity to the deployment setup as well as any restarts that need to happen. \ No newline at end of file diff --git a/azure-pipelines-1.yml b/azure-pipelines-1.yml deleted file mode 100644 index fc6f8f4b3..000000000 --- a/azure-pipelines-1.yml +++ /dev/null @@ -1,9 +0,0 @@ -trigger: -- new-core - -steps: -- script: - git remote add github https://github.com/FoglyOgly/Meowth.git; - git push github new-core - - diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index b76ac8855..000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,13 +0,0 @@ -# Starter pipeline -# Start with a minimal pipeline that you can customize to build and deploy your code. -# Add steps that build, run tests, deploy, and more: -# https://aka.ms/yaml - -trigger: -- new-core - -pr: -- new-core - -steps: -- script: git push origin diff --git a/config/config_template.py b/config/config_template.py new file mode 100644 index 000000000..a0822e34b --- /dev/null +++ b/config/config_template.py @@ -0,0 +1,122 @@ +'''Configuration values for Meowth - Rename to config.py''' + +# bot token from discord developers +bot_token = 'your_token_here' + +# default bot settings +bot_prefix = '!' +bot_master = 12345678903216549878 +bot_coowners = [132314336914833409, 263607303096369152] +preload_extensions = ['raid','map','pkmn','research','rocket','wild','users','admin'] +version = '3' + +# minimum required permissions for bot user +bot_permissions = 18135768366161 + +# postgresql database credentials +db_details = { + # 'username' : 'meowth', + # 'database' : 'meowth', + # 'hostname' : 'localhost', + 'password' : 'password' +} + +dbdocid = 'google_sheet_id_here' + +emoji = { + 'maybe' : '🙋', + 'coming' : '🚗', + 'here' : '<:here:350686955316445185>', + 'remote' : '🛰', + 'invite' : '✉', + 'cancel' : '❌' +} + +# default language +lang_bot = 'en' +lang_pkmn = 'en' + +# team settings +team_list = ['mystic', 'valor', 'instinct'] +team_colours = { + "mystic" : "0x3498db", + "valor" : "0xe74c3c", + "instinct" : "0xf1c40f" +} + +team_emoji = { + "mystic" : "<:mystic:351758303912656896>", + "valor" : "<:valor:351758298975830016>", + "instinct" : "<:instinct:351758298627702786>", + "unknown" : "\u2754" +} + +pkbtlr_emoji = { + 'pkbtlr' : '<:pkbtlr:1150901168176894113>' +} + +form_emoji = { + 'shadow' : '<:shadow:1165329645496788434>', + 'purified' : '<:purified:1163456644170522706>' +} + +# raid settings +allow_assume = { + "5" : "False", + "4" : "False", + "3" : "False", + "2" : "False", + "1" : "False" +} + +status_emoji = { + "omw" : ":omw:", + "here" : ":here:" +} + +type_emoji = { + "bug" : { "typeid" : "POKEMON_TYPE_BUG", "emoji" : "<:bug1:351758295196893185>", "weather" : "RAINY" }, + "dark" : { "typeid" : "POKEMON_TYPE_DARK", "emoji" : "<:dark:351758294316089356>", "weather" : "FOG" }, + "dragon" : { "typeid" : "POKEMON_TYPE_DRAGON", "emoji" : "<:dragon1:351758295612129280>", "weather" : "WINDY" }, + "electric" : { "typeid" : "POKEMON_TYPE_ELECTRIC", "emoji" : "<:electric:351758295414865921>", "weather" : "RAINY" }, + "fairy" : { "typeid" : "POKEMON_TYPE_FAIRY", "emoji" : "<:fairy1:351758295070932992>", "weather" : "OVERCAST" }, + "fighting" : { "typeid" : "POKEMON_TYPE_FIGHTING", "emoji" : "<:fighting:351758296090148864>", "weather" : "OVERCAST" }, + "fire" : { "typeid" : "POKEMON_TYPE_FIRE", "emoji" : "<:fire1:351758296044142624>", "weather" : "CLEAR" }, + "flying" : { "typeid" : "POKEMON_TYPE_FLYING", "emoji" : "<:flying:351758295033446400>", "weather" : "WINDY" }, + "ghost" : { "typeid" : "POKEMON_TYPE_GHOST", "emoji" : "<:ghost1:351758295683432449>", "weather" : "FOG" }, + "grass" : { "typeid" : "POKEMON_TYPE_GRASS", "emoji" : "<:grass:351758295729700868>", "weather" : "CLEAR" }, + "ground" : { "typeid" : "POKEMON_TYPE_GROUND", "emoji" : "<:ground:351758295968776194>", "weather" : "CLEAR" }, + "ice" : { "typeid" : "POKEMON_TYPE_ICE", "emoji" : "<:ice:351758296111120384>", "weather" : "SNOW" }, + "normal" : { "typeid" : "POKEMON_TYPE_NORMAL", "emoji" : "<:normal:351758296409178112>", "weather" : "PARTLY_CLOUDY" }, + "poison" : { "typeid" : "POKEMON_TYPE_POISON", "emoji" : "<:poison:351758295976902679>", "weather" : "OVERCAST" }, + "psychic" : { "typeid" : "POKEMON_TYPE_PSYCHIC", "emoji" : "<:psychic:351758294744039426>", "weather" : "WINDY" }, + "rock" : { "typeid" : "POKEMON_TYPE_ROCK", "emoji" : "<:rock1:351758296077697024>", "weather" : "PARTLY_CLOUDY" }, + "steel" : { "typeid" : "POKEMON_TYPE_STEEL", "emoji" : "<:steel:351758296425955328>", "weather" : "SNOW" }, + "water" : { "typeid" : "POKEMON_TYPE_WATER", "emoji" : "<:water:351758295142498325>", "weather" : "RAINY" } +} + +raid_expire_grace_period = "15m" + +# weatherapikey = +# gmapsapikey = + +max_report_distance = 20 + +# help command categories +command_categories = { + "Owner" : { + "index" : "5", + "description" : "Owner-only commands for bot config or info." + }, + "Server Config" : { + "index" : "10", + "description" : "Server configuration commands." + }, + "Bot Info" : { + "index" : "15", + "description" : "Commands for finding out information on the bot." + }, +} + +# analytics/statistics +pokebattler_tracker = "MeowthSelfHoster" diff --git a/database/schema.sql b/database/schema.sql index 17ea45ece..b75431702 100644 --- a/database/schema.sql +++ b/database/schema.sql @@ -37,7 +37,7 @@ COMMENT ON EXTENSION adminpack IS 'administrative functions for PostgreSQL'; -- -- TOC entry 280 (class 1255 OID 16409) --- Name: cancel(); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: cancel(); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.cancel() RETURNS trigger @@ -53,11 +53,11 @@ END; $$; -ALTER FUNCTION public.cancel() OWNER TO postgres; +ALTER FUNCTION public.cancel() OWNER TO meowth; -- -- TOC entry 281 (class 1255 OID 16410) --- Name: enable_forecast(); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: enable_forecast(); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.enable_forecast() RETURNS trigger @@ -70,11 +70,11 @@ END; $$; -ALTER FUNCTION public.enable_forecast() OWNER TO postgres; +ALTER FUNCTION public.enable_forecast() OWNER TO meowth; -- -- TOC entry 282 (class 1255 OID 16411) --- Name: get_message_ids(bigint); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: get_message_ids(bigint); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.get_message_ids(bigint) RETURNS text[] @@ -84,11 +84,11 @@ SELECT messages FROM raids WHERE id = $1 $_$; -ALTER FUNCTION public.get_message_ids(bigint) OWNER TO postgres; +ALTER FUNCTION public.get_message_ids(bigint) OWNER TO meowth; -- -- TOC entry 283 (class 1255 OID 16412) --- Name: get_raid_messages(bigint); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: get_raid_messages(bigint); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.get_raid_messages(x bigint) RETURNS text[] @@ -103,11 +103,11 @@ END; $$; -ALTER FUNCTION public.get_raid_messages(x bigint) OWNER TO postgres; +ALTER FUNCTION public.get_raid_messages(x bigint) OWNER TO meowth; -- -- TOC entry 284 (class 1255 OID 16413) --- Name: insert_reverse_travel(); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: insert_reverse_travel(); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.insert_reverse_travel() RETURNS trigger @@ -123,11 +123,11 @@ END; $$; -ALTER FUNCTION public.insert_reverse_travel() OWNER TO postgres; +ALTER FUNCTION public.insert_reverse_travel() OWNER TO meowth; -- -- TOC entry 285 (class 1255 OID 16414) --- Name: notify_messages(bigint, text[]); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: notify_messages(bigint, text[]); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.notify_messages(raidid bigint, list text[]) RETURNS void @@ -139,11 +139,11 @@ END; $$; -ALTER FUNCTION public.notify_messages(raidid bigint, list text[]) OWNER TO postgres; +ALTER FUNCTION public.notify_messages(raidid bigint, list text[]) OWNER TO meowth; -- -- TOC entry 286 (class 1255 OID 16415) --- Name: rsvp_notify(); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: rsvp_notify(); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.rsvp_notify() RETURNS trigger @@ -155,11 +155,11 @@ END; $$; -ALTER FUNCTION public.rsvp_notify() OWNER TO postgres; +ALTER FUNCTION public.rsvp_notify() OWNER TO meowth; -- -- TOC entry 287 (class 1255 OID 16416) --- Name: unhere(); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: unhere(); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.unhere() RETURNS trigger @@ -178,11 +178,11 @@ END; $$; -ALTER FUNCTION public.unhere() OWNER TO postgres; +ALTER FUNCTION public.unhere() OWNER TO meowth; -- -- TOC entry 288 (class 1255 OID 16417) --- Name: update_cells(); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: update_cells(); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.update_cells() RETURNS trigger @@ -202,11 +202,11 @@ END; $$; -ALTER FUNCTION public.update_cells() OWNER TO postgres; +ALTER FUNCTION public.update_cells() OWNER TO meowth; -- -- TOC entry 289 (class 1255 OID 16418) --- Name: update_meetuprsvp(); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: update_meetuprsvp(); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.update_meetuprsvp() RETURNS trigger @@ -232,11 +232,11 @@ END; $$; -ALTER FUNCTION public.update_meetuprsvp() OWNER TO postgres; +ALTER FUNCTION public.update_meetuprsvp() OWNER TO meowth; -- -- TOC entry 290 (class 1255 OID 16419) --- Name: update_raid_weather(); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: update_raid_weather(); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.update_raid_weather() RETURNS trigger @@ -257,11 +257,11 @@ END; $$; -ALTER FUNCTION public.update_raid_weather() OWNER TO postgres; +ALTER FUNCTION public.update_raid_weather() OWNER TO meowth; -- -- TOC entry 302 (class 1255 OID 16420) --- Name: update_rsvp(); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: update_rsvp(); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.update_rsvp() RETURNS trigger @@ -303,11 +303,11 @@ END; $$; -ALTER FUNCTION public.update_rsvp() OWNER TO postgres; +ALTER FUNCTION public.update_rsvp() OWNER TO meowth; -- -- TOC entry 303 (class 1255 OID 16421) --- Name: update_trainrsvp(); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: update_trainrsvp(); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.update_trainrsvp() RETURNS trigger @@ -336,11 +336,11 @@ END; $$; -ALTER FUNCTION public.update_trainrsvp() OWNER TO postgres; +ALTER FUNCTION public.update_trainrsvp() OWNER TO meowth; -- -- TOC entry 304 (class 1255 OID 16422) --- Name: update_weather(); Type: FUNCTION; Schema: public; Owner: postgres +-- Name: update_weather(); Type: FUNCTION; Schema: public; Owner: meowth -- CREATE FUNCTION public.update_weather() RETURNS void @@ -356,7 +356,7 @@ END; $$; -ALTER FUNCTION public.update_weather() OWNER TO postgres; +ALTER FUNCTION public.update_weather() OWNER TO meowth; SET default_tablespace = ''; @@ -364,7 +364,7 @@ SET default_table_access_method = heap; -- -- TOC entry 215 (class 1259 OID 16423) --- Name: accuweather; Type: TABLE; Schema: public; Owner: postgres +-- Name: accuweather; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.accuweather ( @@ -374,11 +374,11 @@ CREATE TABLE public.accuweather ( ); -ALTER TABLE public.accuweather OWNER TO postgres; +ALTER TABLE public.accuweather OWNER TO meowth; -- -- TOC entry 216 (class 1259 OID 16428) --- Name: archive; Type: TABLE; Schema: public; Owner: postgres +-- Name: archive; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.archive ( @@ -388,11 +388,11 @@ CREATE TABLE public.archive ( ); -ALTER TABLE public.archive OWNER TO postgres; +ALTER TABLE public.archive OWNER TO meowth; -- -- TOC entry 217 (class 1259 OID 16433) --- Name: command_log; Type: TABLE; Schema: public; Owner: postgres +-- Name: command_log; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.command_log ( @@ -411,11 +411,11 @@ CREATE TABLE public.command_log ( ); -ALTER TABLE public.command_log OWNER TO postgres; +ALTER TABLE public.command_log OWNER TO meowth; -- -- TOC entry 218 (class 1259 OID 16439) --- Name: counters_data; Type: TABLE; Schema: public; Owner: postgres +-- Name: counters_data; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.counters_data ( @@ -447,11 +447,11 @@ CREATE TABLE public.counters_data ( ); -ALTER TABLE public.counters_data OWNER TO postgres; +ALTER TABLE public.counters_data OWNER TO meowth; -- -- TOC entry 219 (class 1259 OID 16444) --- Name: cpm_table; Type: TABLE; Schema: public; Owner: postgres +-- Name: cpm_table; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.cpm_table ( @@ -460,11 +460,11 @@ CREATE TABLE public.cpm_table ( ); -ALTER TABLE public.cpm_table OWNER TO postgres; +ALTER TABLE public.cpm_table OWNER TO meowth; -- -- TOC entry 220 (class 1259 OID 16447) --- Name: current_weather; Type: TABLE; Schema: public; Owner: postgres +-- Name: current_weather; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.current_weather ( @@ -476,11 +476,11 @@ CREATE TABLE public.current_weather ( ); -ALTER TABLE public.current_weather OWNER TO postgres; +ALTER TABLE public.current_weather OWNER TO meowth; -- -- TOC entry 221 (class 1259 OID 16452) --- Name: custom_roles; Type: TABLE; Schema: public; Owner: postgres +-- Name: custom_roles; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.custom_roles ( @@ -489,11 +489,11 @@ CREATE TABLE public.custom_roles ( ); -ALTER TABLE public.custom_roles OWNER TO postgres; +ALTER TABLE public.custom_roles OWNER TO meowth; -- -- TOC entry 222 (class 1259 OID 16455) --- Name: discord_logs; Type: TABLE; Schema: public; Owner: postgres +-- Name: discord_logs; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.discord_logs ( @@ -510,11 +510,11 @@ CREATE TABLE public.discord_logs ( ); -ALTER TABLE public.discord_logs OWNER TO postgres; +ALTER TABLE public.discord_logs OWNER TO meowth; -- -- TOC entry 223 (class 1259 OID 16460) --- Name: discord_messages; Type: TABLE; Schema: public; Owner: postgres +-- Name: discord_messages; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.discord_messages ( @@ -533,11 +533,11 @@ CREATE TABLE public.discord_messages ( ); -ALTER TABLE public.discord_messages OWNER TO postgres; +ALTER TABLE public.discord_messages OWNER TO meowth; -- -- TOC entry 224 (class 1259 OID 16467) --- Name: forecast_config; Type: TABLE; Schema: public; Owner: postgres +-- Name: forecast_config; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.forecast_config ( @@ -547,11 +547,11 @@ CREATE TABLE public.forecast_config ( ); -ALTER TABLE public.forecast_config OWNER TO postgres; +ALTER TABLE public.forecast_config OWNER TO meowth; -- -- TOC entry 225 (class 1259 OID 16470) --- Name: form_names; Type: TABLE; Schema: public; Owner: postgres +-- Name: form_names; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.form_names ( @@ -561,11 +561,11 @@ CREATE TABLE public.form_names ( ); -ALTER TABLE public.form_names OWNER TO postgres; +ALTER TABLE public.form_names OWNER TO meowth; -- -- TOC entry 226 (class 1259 OID 16475) --- Name: forms; Type: TABLE; Schema: public; Owner: postgres +-- Name: forms; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.forms ( @@ -574,11 +574,11 @@ CREATE TABLE public.forms ( ); -ALTER TABLE public.forms OWNER TO postgres; +ALTER TABLE public.forms OWNER TO meowth; -- -- TOC entry 227 (class 1259 OID 16480) --- Name: guild_config; Type: TABLE; Schema: public; Owner: postgres +-- Name: guild_config; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.guild_config ( @@ -588,11 +588,11 @@ CREATE TABLE public.guild_config ( ); -ALTER TABLE public.guild_config OWNER TO postgres; +ALTER TABLE public.guild_config OWNER TO meowth; -- -- TOC entry 228 (class 1259 OID 16485) --- Name: guild_settings; Type: TABLE; Schema: public; Owner: postgres +-- Name: guild_settings; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.guild_settings ( @@ -601,11 +601,11 @@ CREATE TABLE public.guild_settings ( ); -ALTER TABLE public.guild_settings OWNER TO postgres; +ALTER TABLE public.guild_settings OWNER TO meowth; -- -- TOC entry 229 (class 1259 OID 16490) --- Name: gym_travel; Type: TABLE; Schema: public; Owner: postgres +-- Name: gym_travel; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.gym_travel ( @@ -615,11 +615,11 @@ CREATE TABLE public.gym_travel ( ); -ALTER TABLE public.gym_travel OWNER TO postgres; +ALTER TABLE public.gym_travel OWNER TO meowth; -- -- TOC entry 230 (class 1259 OID 16493) --- Name: gyms; Type: TABLE; Schema: public; Owner: postgres +-- Name: gyms; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.gyms ( @@ -634,11 +634,11 @@ CREATE TABLE public.gyms ( ); -ALTER TABLE public.gyms OWNER TO postgres; +ALTER TABLE public.gyms OWNER TO meowth; -- -- TOC entry 231 (class 1259 OID 16498) --- Name: gyms_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- Name: gyms_id_seq; Type: SEQUENCE; Schema: public; Owner: meowth -- CREATE SEQUENCE public.gyms_id_seq @@ -649,12 +649,12 @@ CREATE SEQUENCE public.gyms_id_seq CACHE 1; -ALTER TABLE public.gyms_id_seq OWNER TO postgres; +ALTER TABLE public.gyms_id_seq OWNER TO meowth; -- -- TOC entry 3711 (class 0 OID 0) -- Dependencies: 231 --- Name: gyms_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- Name: gyms_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: meowth -- ALTER SEQUENCE public.gyms_id_seq OWNED BY public.gyms.id; @@ -662,7 +662,7 @@ ALTER SEQUENCE public.gyms_id_seq OWNED BY public.gyms.id; -- -- TOC entry 232 (class 1259 OID 16499) --- Name: integers; Type: SEQUENCE; Schema: public; Owner: postgres +-- Name: integers; Type: SEQUENCE; Schema: public; Owner: meowth -- CREATE SEQUENCE public.integers @@ -673,11 +673,11 @@ CREATE SEQUENCE public.integers CACHE 1; -ALTER TABLE public.integers OWNER TO postgres; +ALTER TABLE public.integers OWNER TO meowth; -- -- TOC entry 233 (class 1259 OID 16500) --- Name: item_names; Type: TABLE; Schema: public; Owner: postgres +-- Name: item_names; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.item_names ( @@ -687,11 +687,11 @@ CREATE TABLE public.item_names ( ); -ALTER TABLE public.item_names OWNER TO postgres; +ALTER TABLE public.item_names OWNER TO meowth; -- -- TOC entry 234 (class 1259 OID 16505) --- Name: languages; Type: TABLE; Schema: public; Owner: postgres +-- Name: languages; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.languages ( @@ -703,11 +703,11 @@ CREATE TABLE public.languages ( ); -ALTER TABLE public.languages OWNER TO postgres; +ALTER TABLE public.languages OWNER TO meowth; -- -- TOC entry 235 (class 1259 OID 16510) --- Name: meetup_rsvp; Type: TABLE; Schema: public; Owner: postgres +-- Name: meetup_rsvp; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.meetup_rsvp ( @@ -718,11 +718,11 @@ CREATE TABLE public.meetup_rsvp ( ); -ALTER TABLE public.meetup_rsvp OWNER TO postgres; +ALTER TABLE public.meetup_rsvp OWNER TO meowth; -- -- TOC entry 236 (class 1259 OID 16515) --- Name: meetups; Type: TABLE; Schema: public; Owner: postgres +-- Name: meetups; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.meetups ( @@ -738,11 +738,11 @@ CREATE TABLE public.meetups ( ); -ALTER TABLE public.meetups OWNER TO postgres; +ALTER TABLE public.meetups OWNER TO meowth; -- -- TOC entry 237 (class 1259 OID 16520) --- Name: meowth_logs; Type: TABLE; Schema: public; Owner: postgres +-- Name: meowth_logs; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.meowth_logs ( @@ -759,11 +759,11 @@ CREATE TABLE public.meowth_logs ( ); -ALTER TABLE public.meowth_logs OWNER TO postgres; +ALTER TABLE public.meowth_logs OWNER TO meowth; -- -- TOC entry 238 (class 1259 OID 16525) --- Name: modifiers; Type: TABLE; Schema: public; Owner: postgres +-- Name: modifiers; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.modifiers ( @@ -778,11 +778,11 @@ CREATE TABLE public.modifiers ( ); -ALTER TABLE public.modifiers OWNER TO postgres; +ALTER TABLE public.modifiers OWNER TO meowth; -- -- TOC entry 239 (class 1259 OID 16530) --- Name: move_names; Type: TABLE; Schema: public; Owner: postgres +-- Name: move_names; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.move_names ( @@ -792,11 +792,11 @@ CREATE TABLE public.move_names ( ); -ALTER TABLE public.move_names OWNER TO postgres; +ALTER TABLE public.move_names OWNER TO meowth; -- -- TOC entry 240 (class 1259 OID 16535) --- Name: moves; Type: TABLE; Schema: public; Owner: postgres +-- Name: moves; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.moves ( @@ -813,11 +813,11 @@ CREATE TABLE public.moves ( ); -ALTER TABLE public.moves OWNER TO postgres; +ALTER TABLE public.moves OWNER TO meowth; -- -- TOC entry 241 (class 1259 OID 16540) --- Name: movesets; Type: TABLE; Schema: public; Owner: postgres +-- Name: movesets; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.movesets ( @@ -827,11 +827,11 @@ CREATE TABLE public.movesets ( ); -ALTER TABLE public.movesets OWNER TO postgres; +ALTER TABLE public.movesets OWNER TO meowth; -- -- TOC entry 242 (class 1259 OID 16545) --- Name: pokedex; Type: TABLE; Schema: public; Owner: postgres +-- Name: pokedex; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.pokedex ( @@ -843,11 +843,11 @@ CREATE TABLE public.pokedex ( ); -ALTER TABLE public.pokedex OWNER TO postgres; +ALTER TABLE public.pokedex OWNER TO meowth; -- -- TOC entry 243 (class 1259 OID 16550) --- Name: pokemon; Type: TABLE; Schema: public; Owner: postgres +-- Name: pokemon; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.pokemon ( @@ -884,11 +884,11 @@ CREATE TABLE public.pokemon ( ); -ALTER TABLE public.pokemon OWNER TO postgres; +ALTER TABLE public.pokemon OWNER TO meowth; -- -- TOC entry 244 (class 1259 OID 16555) --- Name: pokestops; Type: TABLE; Schema: public; Owner: postgres +-- Name: pokestops; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.pokestops ( @@ -902,11 +902,11 @@ CREATE TABLE public.pokestops ( ); -ALTER TABLE public.pokestops OWNER TO postgres; +ALTER TABLE public.pokestops OWNER TO meowth; -- -- TOC entry 245 (class 1259 OID 16560) --- Name: pokestops_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- Name: pokestops_id_seq; Type: SEQUENCE; Schema: public; Owner: meowth -- CREATE SEQUENCE public.pokestops_id_seq @@ -917,12 +917,12 @@ CREATE SEQUENCE public.pokestops_id_seq CACHE 1; -ALTER TABLE public.pokestops_id_seq OWNER TO postgres; +ALTER TABLE public.pokestops_id_seq OWNER TO meowth; -- -- TOC entry 3712 (class 0 OID 0) -- Dependencies: 245 --- Name: pokestops_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- Name: pokestops_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: meowth -- ALTER SEQUENCE public.pokestops_id_seq OWNED BY public.pokestops.id; @@ -930,7 +930,7 @@ ALTER SEQUENCE public.pokestops_id_seq OWNED BY public.pokestops.id; -- -- TOC entry 246 (class 1259 OID 16561) --- Name: prefixes; Type: TABLE; Schema: public; Owner: postgres +-- Name: prefixes; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.prefixes ( @@ -939,11 +939,11 @@ CREATE TABLE public.prefixes ( ); -ALTER TABLE public.prefixes OWNER TO postgres; +ALTER TABLE public.prefixes OWNER TO meowth; -- -- TOC entry 247 (class 1259 OID 16566) --- Name: raid_bosses; Type: TABLE; Schema: public; Owner: postgres +-- Name: raid_bosses; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.raid_bosses ( @@ -958,11 +958,11 @@ CREATE TABLE public.raid_bosses ( ); -ALTER TABLE public.raid_bosses OWNER TO postgres; +ALTER TABLE public.raid_bosses OWNER TO meowth; -- -- TOC entry 248 (class 1259 OID 16571) --- Name: raid_groups; Type: TABLE; Schema: public; Owner: postgres +-- Name: raid_groups; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.raid_groups ( @@ -974,11 +974,11 @@ CREATE TABLE public.raid_groups ( ); -ALTER TABLE public.raid_groups OWNER TO postgres; +ALTER TABLE public.raid_groups OWNER TO meowth; -- -- TOC entry 249 (class 1259 OID 16576) --- Name: raid_groups_grp_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- Name: raid_groups_grp_id_seq; Type: SEQUENCE; Schema: public; Owner: meowth -- CREATE SEQUENCE public.raid_groups_grp_id_seq @@ -989,12 +989,12 @@ CREATE SEQUENCE public.raid_groups_grp_id_seq CACHE 1; -ALTER TABLE public.raid_groups_grp_id_seq OWNER TO postgres; +ALTER TABLE public.raid_groups_grp_id_seq OWNER TO meowth; -- -- TOC entry 3713 (class 0 OID 0) -- Dependencies: 249 --- Name: raid_groups_grp_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- Name: raid_groups_grp_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: meowth -- ALTER SEQUENCE public.raid_groups_grp_id_seq OWNED BY public.raid_groups.grp_id; @@ -1002,7 +1002,7 @@ ALTER SEQUENCE public.raid_groups_grp_id_seq OWNED BY public.raid_groups.grp_id; -- -- TOC entry 250 (class 1259 OID 16577) --- Name: raid_rsvp; Type: TABLE; Schema: public; Owner: postgres +-- Name: raid_rsvp; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.raid_rsvp ( @@ -1017,11 +1017,11 @@ CREATE TABLE public.raid_rsvp ( ); -ALTER TABLE public.raid_rsvp OWNER TO postgres; +ALTER TABLE public.raid_rsvp OWNER TO meowth; -- -- TOC entry 251 (class 1259 OID 16583) --- Name: raids; Type: TABLE; Schema: public; Owner: postgres +-- Name: raids; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.raids ( @@ -1042,11 +1042,11 @@ CREATE TABLE public.raids ( ); -ALTER TABLE public.raids OWNER TO postgres; +ALTER TABLE public.raids OWNER TO meowth; -- -- TOC entry 252 (class 1259 OID 16588) --- Name: raids_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- Name: raids_id_seq; Type: SEQUENCE; Schema: public; Owner: meowth -- CREATE SEQUENCE public.raids_id_seq @@ -1057,12 +1057,12 @@ CREATE SEQUENCE public.raids_id_seq CACHE 1; -ALTER TABLE public.raids_id_seq OWNER TO postgres; +ALTER TABLE public.raids_id_seq OWNER TO meowth; -- -- TOC entry 3714 (class 0 OID 0) -- Dependencies: 252 --- Name: raids_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- Name: raids_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: meowth -- ALTER SEQUENCE public.raids_id_seq OWNED BY public.raids.id; @@ -1070,7 +1070,7 @@ ALTER SEQUENCE public.raids_id_seq OWNED BY public.raids.id; -- -- TOC entry 253 (class 1259 OID 16589) --- Name: regional_raids; Type: TABLE; Schema: public; Owner: postgres +-- Name: regional_raids; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.regional_raids ( @@ -1082,11 +1082,11 @@ CREATE TABLE public.regional_raids ( ); -ALTER TABLE public.regional_raids OWNER TO postgres; +ALTER TABLE public.regional_raids OWNER TO meowth; -- -- TOC entry 254 (class 1259 OID 16594) --- Name: report_channels; Type: TABLE; Schema: public; Owner: postgres +-- Name: report_channels; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.report_channels ( @@ -1114,15 +1114,24 @@ CREATE TABLE public.report_channels ( meetup boolean, category_meetup numeric(20,0), rocket boolean, - category_7 text + category_6 text, + category_7 text, + category_8 text, + category_9 text, + category_10 text, + category_11 text, + category_12 text, + category_13 text, + category_14 text, + category_15 text ); -ALTER TABLE public.report_channels OWNER TO postgres; +ALTER TABLE public.report_channels OWNER TO meowth; -- -- TOC entry 255 (class 1259 OID 16606) --- Name: research; Type: TABLE; Schema: public; Owner: postgres +-- Name: research; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.research ( @@ -1139,11 +1148,11 @@ CREATE TABLE public.research ( ); -ALTER TABLE public.research OWNER TO postgres; +ALTER TABLE public.research OWNER TO meowth; -- -- TOC entry 256 (class 1259 OID 16611) --- Name: research_tasks; Type: TABLE; Schema: public; Owner: postgres +-- Name: research_tasks; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.research_tasks ( @@ -1152,11 +1161,11 @@ CREATE TABLE public.research_tasks ( ); -ALTER TABLE public.research_tasks OWNER TO postgres; +ALTER TABLE public.research_tasks OWNER TO meowth; -- -- TOC entry 257 (class 1259 OID 16616) --- Name: restart_savedata; Type: TABLE; Schema: public; Owner: postgres +-- Name: restart_savedata; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.restart_savedata ( @@ -1168,11 +1177,11 @@ CREATE TABLE public.restart_savedata ( ); -ALTER TABLE public.restart_savedata OWNER TO postgres; +ALTER TABLE public.restart_savedata OWNER TO meowth; -- -- TOC entry 258 (class 1259 OID 16619) --- Name: rockets; Type: TABLE; Schema: public; Owner: postgres +-- Name: rockets; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.rockets ( @@ -1187,11 +1196,11 @@ CREATE TABLE public.rockets ( ); -ALTER TABLE public.rockets OWNER TO postgres; +ALTER TABLE public.rockets OWNER TO meowth; -- -- TOC entry 259 (class 1259 OID 16624) --- Name: scoreboard; Type: TABLE; Schema: public; Owner: postgres +-- Name: scoreboard; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.scoreboard ( @@ -1205,11 +1214,11 @@ CREATE TABLE public.scoreboard ( ); -ALTER TABLE public.scoreboard OWNER TO postgres; +ALTER TABLE public.scoreboard OWNER TO meowth; -- -- TOC entry 260 (class 1259 OID 16627) --- Name: task_names; Type: TABLE; Schema: public; Owner: postgres +-- Name: task_names; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.task_names ( @@ -1220,11 +1229,11 @@ CREATE TABLE public.task_names ( ); -ALTER TABLE public.task_names OWNER TO postgres; +ALTER TABLE public.task_names OWNER TO meowth; -- -- TOC entry 261 (class 1259 OID 16632) --- Name: team_names; Type: TABLE; Schema: public; Owner: postgres +-- Name: team_names; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.team_names ( @@ -1234,11 +1243,11 @@ CREATE TABLE public.team_names ( ); -ALTER TABLE public.team_names OWNER TO postgres; +ALTER TABLE public.team_names OWNER TO meowth; -- -- TOC entry 262 (class 1259 OID 16637) --- Name: team_roles; Type: TABLE; Schema: public; Owner: postgres +-- Name: team_roles; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.team_roles ( @@ -1249,11 +1258,11 @@ CREATE TABLE public.team_roles ( ); -ALTER TABLE public.team_roles OWNER TO postgres; +ALTER TABLE public.team_roles OWNER TO meowth; -- -- TOC entry 263 (class 1259 OID 16640) --- Name: teams; Type: TABLE; Schema: public; Owner: postgres +-- Name: teams; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.teams ( @@ -1264,11 +1273,11 @@ CREATE TABLE public.teams ( ); -ALTER TABLE public.teams OWNER TO postgres; +ALTER TABLE public.teams OWNER TO meowth; -- -- TOC entry 264 (class 1259 OID 16645) --- Name: to_archive; Type: TABLE; Schema: public; Owner: postgres +-- Name: to_archive; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.to_archive ( @@ -1278,11 +1287,11 @@ CREATE TABLE public.to_archive ( ); -ALTER TABLE public.to_archive OWNER TO postgres; +ALTER TABLE public.to_archive OWNER TO meowth; -- -- TOC entry 265 (class 1259 OID 16650) --- Name: trades; Type: TABLE; Schema: public; Owner: postgres +-- Name: trades; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.trades ( @@ -1296,11 +1305,11 @@ CREATE TABLE public.trades ( ); -ALTER TABLE public.trades OWNER TO postgres; +ALTER TABLE public.trades OWNER TO meowth; -- -- TOC entry 266 (class 1259 OID 16655) --- Name: trades_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- Name: trades_id_seq; Type: SEQUENCE; Schema: public; Owner: meowth -- CREATE SEQUENCE public.trades_id_seq @@ -1311,12 +1320,12 @@ CREATE SEQUENCE public.trades_id_seq CACHE 1; -ALTER TABLE public.trades_id_seq OWNER TO postgres; +ALTER TABLE public.trades_id_seq OWNER TO meowth; -- -- TOC entry 3715 (class 0 OID 0) -- Dependencies: 266 --- Name: trades_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- Name: trades_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: meowth -- ALTER SEQUENCE public.trades_id_seq OWNED BY public.trades.id; @@ -1324,7 +1333,7 @@ ALTER SEQUENCE public.trades_id_seq OWNED BY public.trades.id; -- -- TOC entry 267 (class 1259 OID 16656) --- Name: train_rsvp; Type: TABLE; Schema: public; Owner: postgres +-- Name: train_rsvp; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.train_rsvp ( @@ -1334,11 +1343,11 @@ CREATE TABLE public.train_rsvp ( ); -ALTER TABLE public.train_rsvp OWNER TO postgres; +ALTER TABLE public.train_rsvp OWNER TO meowth; -- -- TOC entry 268 (class 1259 OID 16661) --- Name: trains; Type: TABLE; Schema: public; Owner: postgres +-- Name: trains; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.trains ( @@ -1355,11 +1364,11 @@ CREATE TABLE public.trains ( ); -ALTER TABLE public.trains OWNER TO postgres; +ALTER TABLE public.trains OWNER TO meowth; -- -- TOC entry 269 (class 1259 OID 16666) --- Name: type_chart; Type: TABLE; Schema: public; Owner: postgres +-- Name: type_chart; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.type_chart ( @@ -1369,11 +1378,11 @@ CREATE TABLE public.type_chart ( ); -ALTER TABLE public.type_chart OWNER TO postgres; +ALTER TABLE public.type_chart OWNER TO meowth; -- -- TOC entry 270 (class 1259 OID 16671) --- Name: types; Type: TABLE; Schema: public; Owner: postgres +-- Name: types; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.types ( @@ -1383,11 +1392,11 @@ CREATE TABLE public.types ( ); -ALTER TABLE public.types OWNER TO postgres; +ALTER TABLE public.types OWNER TO meowth; -- -- TOC entry 271 (class 1259 OID 16676) --- Name: unhandled_errors; Type: TABLE; Schema: public; Owner: postgres +-- Name: unhandled_errors; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.unhandled_errors ( @@ -1400,18 +1409,17 @@ CREATE TABLE public.unhandled_errors ( ); -ALTER TABLE public.unhandled_errors OWNER TO postgres; +ALTER TABLE public.unhandled_errors OWNER TO meowth; -- -- TOC entry 272 (class 1259 OID 16681) --- Name: users; Type: TABLE; Schema: public; Owner: postgres +-- Name: users; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.users ( id numeric(20,0) NOT NULL, team integer, level integer, - silph text, pokebattler integer, party integer[] DEFAULT ARRAY[0, 0, 0, 1], ign text, @@ -1420,11 +1428,11 @@ CREATE TABLE public.users ( ); -ALTER TABLE public.users OWNER TO postgres; +ALTER TABLE public.users OWNER TO meowth; -- -- TOC entry 273 (class 1259 OID 16687) --- Name: wants; Type: TABLE; Schema: public; Owner: postgres +-- Name: wants; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.wants ( @@ -1435,11 +1443,11 @@ CREATE TABLE public.wants ( ); -ALTER TABLE public.wants OWNER TO postgres; +ALTER TABLE public.wants OWNER TO meowth; -- -- TOC entry 274 (class 1259 OID 16692) --- Name: weather_forecasts; Type: TABLE; Schema: public; Owner: postgres +-- Name: weather_forecasts; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.weather_forecasts ( @@ -1457,11 +1465,11 @@ CREATE TABLE public.weather_forecasts ( ); -ALTER TABLE public.weather_forecasts OWNER TO postgres; +ALTER TABLE public.weather_forecasts OWNER TO meowth; -- -- TOC entry 275 (class 1259 OID 16697) --- Name: weather_names; Type: TABLE; Schema: public; Owner: postgres +-- Name: weather_names; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.weather_names ( @@ -1472,11 +1480,11 @@ CREATE TABLE public.weather_names ( ); -ALTER TABLE public.weather_names OWNER TO postgres; +ALTER TABLE public.weather_names OWNER TO meowth; -- -- TOC entry 276 (class 1259 OID 16702) --- Name: web_sessions; Type: TABLE; Schema: public; Owner: postgres +-- Name: web_sessions; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.web_sessions ( @@ -1487,11 +1495,11 @@ CREATE TABLE public.web_sessions ( ); -ALTER TABLE public.web_sessions OWNER TO postgres; +ALTER TABLE public.web_sessions OWNER TO meowth; -- -- TOC entry 277 (class 1259 OID 16707) --- Name: welcome; Type: TABLE; Schema: public; Owner: postgres +-- Name: welcome; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.welcome ( @@ -1501,11 +1509,11 @@ CREATE TABLE public.welcome ( ); -ALTER TABLE public.welcome OWNER TO postgres; +ALTER TABLE public.welcome OWNER TO meowth; -- -- TOC entry 278 (class 1259 OID 16712) --- Name: wilds; Type: TABLE; Schema: public; Owner: postgres +-- Name: wilds; Type: TABLE; Schema: public; Owner: meowth -- CREATE TABLE public.wilds ( @@ -1520,11 +1528,11 @@ CREATE TABLE public.wilds ( ); -ALTER TABLE public.wilds OWNER TO postgres; +ALTER TABLE public.wilds OWNER TO meowth; -- -- TOC entry 279 (class 1259 OID 16717) --- Name: wilds_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- Name: wilds_id_seq; Type: SEQUENCE; Schema: public; Owner: meowth -- CREATE SEQUENCE public.wilds_id_seq @@ -1535,12 +1543,12 @@ CREATE SEQUENCE public.wilds_id_seq CACHE 1; -ALTER TABLE public.wilds_id_seq OWNER TO postgres; +ALTER TABLE public.wilds_id_seq OWNER TO meowth; -- -- TOC entry 3716 (class 0 OID 0) -- Dependencies: 279 --- Name: wilds_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- Name: wilds_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: meowth -- ALTER SEQUENCE public.wilds_id_seq OWNED BY public.wilds.id; @@ -1548,7 +1556,7 @@ ALTER SEQUENCE public.wilds_id_seq OWNED BY public.wilds.id; -- -- TOC entry 3425 (class 2604 OID 16718) --- Name: gyms id; Type: DEFAULT; Schema: public; Owner: postgres +-- Name: gyms id; Type: DEFAULT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.gyms ALTER COLUMN id SET DEFAULT nextval('public.gyms_id_seq'::regclass); @@ -1556,7 +1564,7 @@ ALTER TABLE ONLY public.gyms ALTER COLUMN id SET DEFAULT nextval('public.gyms_id -- -- TOC entry 3426 (class 2604 OID 16719) --- Name: pokestops id; Type: DEFAULT; Schema: public; Owner: postgres +-- Name: pokestops id; Type: DEFAULT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.pokestops ALTER COLUMN id SET DEFAULT nextval('public.pokestops_id_seq'::regclass); @@ -1564,7 +1572,7 @@ ALTER TABLE ONLY public.pokestops ALTER COLUMN id SET DEFAULT nextval('public.po -- -- TOC entry 3427 (class 2604 OID 16720) --- Name: raid_groups grp_id; Type: DEFAULT; Schema: public; Owner: postgres +-- Name: raid_groups grp_id; Type: DEFAULT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.raid_groups ALTER COLUMN grp_id SET DEFAULT nextval('public.raid_groups_grp_id_seq'::regclass); @@ -1572,7 +1580,7 @@ ALTER TABLE ONLY public.raid_groups ALTER COLUMN grp_id SET DEFAULT nextval('pub -- -- TOC entry 3438 (class 2606 OID 32398) --- Name: accuweather accuweather_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: accuweather accuweather_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.accuweather @@ -1581,7 +1589,7 @@ ALTER TABLE ONLY public.accuweather -- -- TOC entry 3440 (class 2606 OID 32400) --- Name: archive archive_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: archive archive_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.archive @@ -1590,7 +1598,7 @@ ALTER TABLE ONLY public.archive -- -- TOC entry 3442 (class 2606 OID 32402) --- Name: command_log command_log_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: command_log command_log_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.command_log @@ -1599,7 +1607,7 @@ ALTER TABLE ONLY public.command_log -- -- TOC entry 3444 (class 2606 OID 32404) --- Name: counters_data counters_data_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: counters_data counters_data_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.counters_data @@ -1608,7 +1616,7 @@ ALTER TABLE ONLY public.counters_data -- -- TOC entry 3446 (class 2606 OID 32406) --- Name: cpm_table cpm_table_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: cpm_table cpm_table_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.cpm_table @@ -1617,7 +1625,7 @@ ALTER TABLE ONLY public.cpm_table -- -- TOC entry 3448 (class 2606 OID 32408) --- Name: current_weather current_weather_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: current_weather current_weather_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.current_weather @@ -1626,7 +1634,7 @@ ALTER TABLE ONLY public.current_weather -- -- TOC entry 3450 (class 2606 OID 32410) --- Name: custom_roles custom_roles_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: custom_roles custom_roles_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.custom_roles @@ -1635,16 +1643,18 @@ ALTER TABLE ONLY public.custom_roles -- -- TOC entry 3452 (class 2606 OID 32412) --- Name: discord_logs discord_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: discord_logs discord_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.discord_logs ADD CONSTRAINT discord_logs_pkey PRIMARY KEY (log_id); +ALTER TABLE ONLY public.discord_messages + ADD CONSTRAINT discord_messages_pkey PRIMARY KEY (message_id, sent); -- -- TOC entry 3454 (class 2606 OID 32501) --- Name: forecast_config forecast_config_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: forecast_config forecast_config_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.forecast_config @@ -1653,7 +1663,7 @@ ALTER TABLE ONLY public.forecast_config -- -- TOC entry 3456 (class 2606 OID 32503) --- Name: form_names form_names_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: form_names form_names_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.form_names @@ -1662,7 +1672,7 @@ ALTER TABLE ONLY public.form_names -- -- TOC entry 3458 (class 2606 OID 32505) --- Name: forms forms_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: forms forms_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.forms @@ -1671,16 +1681,16 @@ ALTER TABLE ONLY public.forms -- -- TOC entry 3460 (class 2606 OID 32507) --- Name: guild_config guild_config_pk; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: guild_config guild_config_pk; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.guild_config - ADD CONSTRAINT guild_config_pk PRIMARY KEY (guild_id, config_name); + ADD CONSTRAINT guild_config_pkey PRIMARY KEY (guild_id, config_name); -- -- TOC entry 3462 (class 2606 OID 32509) --- Name: guild_settings guild_settings_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: guild_settings guild_settings_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.guild_settings @@ -1689,7 +1699,7 @@ ALTER TABLE ONLY public.guild_settings -- -- TOC entry 3464 (class 2606 OID 32511) --- Name: gym_travel gym_travel_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: gym_travel gym_travel_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.gym_travel @@ -1698,7 +1708,7 @@ ALTER TABLE ONLY public.gym_travel -- -- TOC entry 3466 (class 2606 OID 32513) --- Name: gyms gyms_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: gyms gyms_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.gyms @@ -1707,7 +1717,7 @@ ALTER TABLE ONLY public.gyms -- -- TOC entry 3468 (class 2606 OID 32515) --- Name: item_names item_names_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: item_names item_names_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.item_names @@ -1716,7 +1726,7 @@ ALTER TABLE ONLY public.item_names -- -- TOC entry 3470 (class 2606 OID 32517) --- Name: languages languages_identifier_key; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: languages languages_identifier_key; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.languages @@ -1725,7 +1735,7 @@ ALTER TABLE ONLY public.languages -- -- TOC entry 3472 (class 2606 OID 32519) --- Name: languages languages_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: languages languages_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.languages @@ -1734,7 +1744,7 @@ ALTER TABLE ONLY public.languages -- -- TOC entry 3474 (class 2606 OID 32521) --- Name: meetup_rsvp meetup_rsvp_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: meetup_rsvp meetup_rsvp_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.meetup_rsvp @@ -1743,7 +1753,7 @@ ALTER TABLE ONLY public.meetup_rsvp -- -- TOC entry 3476 (class 2606 OID 32523) --- Name: meetups meetups_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: meetups meetups_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.meetups @@ -1752,7 +1762,7 @@ ALTER TABLE ONLY public.meetups -- -- TOC entry 3478 (class 2606 OID 32525) --- Name: meowth_logs meowth_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: meowth_logs meowth_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.meowth_logs @@ -1761,7 +1771,7 @@ ALTER TABLE ONLY public.meowth_logs -- -- TOC entry 3480 (class 2606 OID 32527) --- Name: modifiers modifiers_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: modifiers modifiers_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.modifiers @@ -1770,7 +1780,7 @@ ALTER TABLE ONLY public.modifiers -- -- TOC entry 3482 (class 2606 OID 32529) --- Name: move_names move_names_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: move_names move_names_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.move_names @@ -1779,7 +1789,7 @@ ALTER TABLE ONLY public.move_names -- -- TOC entry 3484 (class 2606 OID 32531) --- Name: moves moves_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: moves moves_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.moves @@ -1788,7 +1798,7 @@ ALTER TABLE ONLY public.moves -- -- TOC entry 3486 (class 2606 OID 32533) --- Name: pokedex pokedex_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: pokedex pokedex_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.pokedex @@ -1797,7 +1807,7 @@ ALTER TABLE ONLY public.pokedex -- -- TOC entry 3488 (class 2606 OID 32535) --- Name: pokemon pokemon_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: pokemon pokemon_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.pokemon @@ -1806,7 +1816,7 @@ ALTER TABLE ONLY public.pokemon -- -- TOC entry 3490 (class 2606 OID 32537) --- Name: pokestops pokestops_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: pokestops pokestops_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.pokestops @@ -1815,7 +1825,7 @@ ALTER TABLE ONLY public.pokestops -- -- TOC entry 3492 (class 2606 OID 32539) --- Name: prefixes prefixes_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: prefixes prefixes_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.prefixes @@ -1824,7 +1834,7 @@ ALTER TABLE ONLY public.prefixes -- -- TOC entry 3494 (class 2606 OID 32541) --- Name: raid_bosses raid_bosses_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: raid_bosses raid_bosses_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.raid_bosses @@ -1833,7 +1843,7 @@ ALTER TABLE ONLY public.raid_bosses -- -- TOC entry 3496 (class 2606 OID 32543) --- Name: raid_groups raid_groups_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: raid_groups raid_groups_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.raid_groups @@ -1842,7 +1852,7 @@ ALTER TABLE ONLY public.raid_groups -- -- TOC entry 3498 (class 2606 OID 32545) --- Name: raid_rsvp raid_rsvp_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: raid_rsvp raid_rsvp_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.raid_rsvp @@ -1851,7 +1861,7 @@ ALTER TABLE ONLY public.raid_rsvp -- -- TOC entry 3500 (class 2606 OID 32547) --- Name: raids raids_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: raids raids_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.raids @@ -1860,7 +1870,7 @@ ALTER TABLE ONLY public.raids -- -- TOC entry 3502 (class 2606 OID 32549) --- Name: regional_raids regional_raids_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: regional_raids regional_raids_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.regional_raids @@ -1869,7 +1879,7 @@ ALTER TABLE ONLY public.regional_raids -- -- TOC entry 3504 (class 2606 OID 32551) --- Name: report_channels report_channels_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: report_channels report_channels_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.report_channels @@ -1878,7 +1888,7 @@ ALTER TABLE ONLY public.report_channels -- -- TOC entry 3506 (class 2606 OID 32553) --- Name: research research_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: research research_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.research @@ -1887,7 +1897,7 @@ ALTER TABLE ONLY public.research -- -- TOC entry 3508 (class 2606 OID 32555) --- Name: research_tasks research_tasks_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: research_tasks research_tasks_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.research_tasks @@ -1896,16 +1906,16 @@ ALTER TABLE ONLY public.research_tasks -- -- TOC entry 3510 (class 2606 OID 32557) --- Name: restart_savedata restart_savedata_pk; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: restart_savedata restart_savedata_pk; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.restart_savedata - ADD CONSTRAINT restart_savedata_pk PRIMARY KEY (restart_snowflake); + ADD CONSTRAINT restart_savedata_pkey PRIMARY KEY (restart_snowflake); -- -- TOC entry 3512 (class 2606 OID 32559) --- Name: rockets rockets_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: rockets rockets_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.rockets @@ -1914,7 +1924,7 @@ ALTER TABLE ONLY public.rockets -- -- TOC entry 3514 (class 2606 OID 32561) --- Name: scoreboard scoreboard_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: scoreboard scoreboard_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.scoreboard @@ -1923,7 +1933,7 @@ ALTER TABLE ONLY public.scoreboard -- -- TOC entry 3516 (class 2606 OID 32563) --- Name: task_names task_names_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: task_names task_names_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.task_names @@ -1932,7 +1942,7 @@ ALTER TABLE ONLY public.task_names -- -- TOC entry 3518 (class 2606 OID 32565) --- Name: team_names team_names_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: team_names team_names_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.team_names @@ -1941,7 +1951,7 @@ ALTER TABLE ONLY public.team_names -- -- TOC entry 3520 (class 2606 OID 32567) --- Name: team_roles team_roles_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: team_roles team_roles_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.team_roles @@ -1950,7 +1960,7 @@ ALTER TABLE ONLY public.team_roles -- -- TOC entry 3522 (class 2606 OID 32569) --- Name: teams teams_color_id_key; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: teams teams_color_id_key; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.teams @@ -1959,7 +1969,7 @@ ALTER TABLE ONLY public.teams -- -- TOC entry 3524 (class 2606 OID 32571) --- Name: teams teams_identifier_key; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: teams teams_identifier_key; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.teams @@ -1968,7 +1978,7 @@ ALTER TABLE ONLY public.teams -- -- TOC entry 3526 (class 2606 OID 32573) --- Name: teams teams_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: teams teams_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.teams @@ -1977,7 +1987,7 @@ ALTER TABLE ONLY public.teams -- -- TOC entry 3528 (class 2606 OID 32575) --- Name: to_archive to_archive_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: to_archive to_archive_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.to_archive @@ -1986,7 +1996,7 @@ ALTER TABLE ONLY public.to_archive -- -- TOC entry 3530 (class 2606 OID 32577) --- Name: trades trades_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: trades trades_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.trades @@ -1995,7 +2005,7 @@ ALTER TABLE ONLY public.trades -- -- TOC entry 3532 (class 2606 OID 32579) --- Name: train_rsvp train_rsvp_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: train_rsvp train_rsvp_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.train_rsvp @@ -2004,7 +2014,7 @@ ALTER TABLE ONLY public.train_rsvp -- -- TOC entry 3534 (class 2606 OID 32581) --- Name: trains trains_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: trains trains_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.trains @@ -2013,7 +2023,7 @@ ALTER TABLE ONLY public.trains -- -- TOC entry 3536 (class 2606 OID 32583) --- Name: type_chart type_chart_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: type_chart type_chart_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.type_chart @@ -2022,7 +2032,7 @@ ALTER TABLE ONLY public.type_chart -- -- TOC entry 3538 (class 2606 OID 32585) --- Name: types types_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: types types_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.types @@ -2031,7 +2041,7 @@ ALTER TABLE ONLY public.types -- -- TOC entry 3540 (class 2606 OID 32587) --- Name: users users_ign_key; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: users users_ign_key; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.users @@ -2040,7 +2050,7 @@ ALTER TABLE ONLY public.users -- -- TOC entry 3542 (class 2606 OID 32589) --- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.users @@ -2049,7 +2059,7 @@ ALTER TABLE ONLY public.users -- -- TOC entry 3544 (class 2606 OID 32591) --- Name: wants wants_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: wants wants_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.wants @@ -2058,7 +2068,7 @@ ALTER TABLE ONLY public.wants -- -- TOC entry 3546 (class 2606 OID 32593) --- Name: weather_forecasts weather_forecasts_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: weather_forecasts weather_forecasts_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.weather_forecasts @@ -2067,7 +2077,7 @@ ALTER TABLE ONLY public.weather_forecasts -- -- TOC entry 3548 (class 2606 OID 32595) --- Name: weather_names weather_names_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: weather_names weather_names_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.weather_names @@ -2076,7 +2086,7 @@ ALTER TABLE ONLY public.weather_names -- -- TOC entry 3550 (class 2606 OID 32597) --- Name: web_sessions web_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: web_sessions web_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.web_sessions @@ -2085,7 +2095,7 @@ ALTER TABLE ONLY public.web_sessions -- -- TOC entry 3552 (class 2606 OID 32599) --- Name: welcome welcome_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: welcome welcome_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.welcome @@ -2094,7 +2104,7 @@ ALTER TABLE ONLY public.welcome -- -- TOC entry 3554 (class 2606 OID 32601) --- Name: wilds wilds_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres +-- Name: wilds wilds_pkey; Type: CONSTRAINT; Schema: public; Owner: meowth -- ALTER TABLE ONLY public.wilds @@ -2103,7 +2113,7 @@ ALTER TABLE ONLY public.wilds -- -- TOC entry 3559 (class 2620 OID 32602) --- Name: meetup_rsvp meetup_rsvp; Type: TRIGGER; Schema: public; Owner: postgres +-- Name: meetup_rsvp meetup_rsvp; Type: TRIGGER; Schema: public; Owner: meowth -- CREATE TRIGGER meetup_rsvp BEFORE INSERT OR DELETE OR UPDATE ON public.meetup_rsvp FOR EACH ROW EXECUTE FUNCTION public.update_meetuprsvp(); @@ -2111,7 +2121,7 @@ CREATE TRIGGER meetup_rsvp BEFORE INSERT OR DELETE OR UPDATE ON public.meetup_rs -- -- TOC entry 3561 (class 2620 OID 32603) --- Name: raid_rsvp notify_rsvp; Type: TRIGGER; Schema: public; Owner: postgres +-- Name: raid_rsvp notify_rsvp; Type: TRIGGER; Schema: public; Owner: meowth -- CREATE TRIGGER notify_rsvp AFTER INSERT OR DELETE OR UPDATE ON public.raid_rsvp FOR EACH ROW EXECUTE FUNCTION public.update_rsvp(); @@ -2119,7 +2129,7 @@ CREATE TRIGGER notify_rsvp AFTER INSERT OR DELETE OR UPDATE ON public.raid_rsvp -- -- TOC entry 3555 (class 2620 OID 32604) --- Name: current_weather notify_weather; Type: TRIGGER; Schema: public; Owner: postgres +-- Name: current_weather notify_weather; Type: TRIGGER; Schema: public; Owner: meowth -- CREATE TRIGGER notify_weather BEFORE INSERT OR UPDATE OF current_weather ON public.current_weather FOR EACH ROW EXECUTE FUNCTION public.update_raid_weather(); @@ -2127,7 +2137,7 @@ CREATE TRIGGER notify_weather BEFORE INSERT OR UPDATE OF current_weather ON publ -- -- TOC entry 3557 (class 2620 OID 32605) --- Name: gym_travel reverse_travel; Type: TRIGGER; Schema: public; Owner: postgres +-- Name: gym_travel reverse_travel; Type: TRIGGER; Schema: public; Owner: meowth -- CREATE TRIGGER reverse_travel AFTER INSERT ON public.gym_travel FOR EACH ROW EXECUTE FUNCTION public.insert_reverse_travel(); @@ -2135,7 +2145,7 @@ CREATE TRIGGER reverse_travel AFTER INSERT ON public.gym_travel FOR EACH ROW EXE -- -- TOC entry 3562 (class 2620 OID 32606) --- Name: train_rsvp train_rsvp; Type: TRIGGER; Schema: public; Owner: postgres +-- Name: train_rsvp train_rsvp; Type: TRIGGER; Schema: public; Owner: meowth -- CREATE TRIGGER train_rsvp BEFORE INSERT OR DELETE OR UPDATE ON public.train_rsvp FOR EACH ROW EXECUTE FUNCTION public.update_trainrsvp(); @@ -2143,7 +2153,7 @@ CREATE TRIGGER train_rsvp BEFORE INSERT OR DELETE OR UPDATE ON public.train_rsvp -- -- TOC entry 3558 (class 2620 OID 32607) --- Name: gyms update_cells; Type: TRIGGER; Schema: public; Owner: postgres +-- Name: gyms update_cells; Type: TRIGGER; Schema: public; Owner: meowth -- CREATE TRIGGER update_cells AFTER INSERT ON public.gyms FOR EACH ROW EXECUTE FUNCTION public.update_cells(); @@ -2151,7 +2161,7 @@ CREATE TRIGGER update_cells AFTER INSERT ON public.gyms FOR EACH ROW EXECUTE FUN -- -- TOC entry 3560 (class 2620 OID 32608) --- Name: pokestops update_cells; Type: TRIGGER; Schema: public; Owner: postgres +-- Name: pokestops update_cells; Type: TRIGGER; Schema: public; Owner: meowth -- CREATE TRIGGER update_cells AFTER INSERT ON public.pokestops FOR EACH ROW EXECUTE FUNCTION public.update_cells(); @@ -2159,7 +2169,7 @@ CREATE TRIGGER update_cells AFTER INSERT ON public.pokestops FOR EACH ROW EXECUT -- -- TOC entry 3556 (class 2620 OID 32609) --- Name: forecast_config update_forecast_config; Type: TRIGGER; Schema: public; Owner: postgres +-- Name: forecast_config update_forecast_config; Type: TRIGGER; Schema: public; Owner: meowth -- CREATE TRIGGER update_forecast_config AFTER INSERT OR UPDATE ON public.forecast_config FOR EACH ROW EXECUTE FUNCTION public.enable_forecast(); diff --git a/emoji.rar b/emoji.rar index 415cd3513..99a996a4b 100644 Binary files a/emoji.rar and b/emoji.rar differ diff --git a/emoji/bug1.png b/emoji/bug1.png new file mode 100644 index 000000000..e905fd094 Binary files /dev/null and b/emoji/bug1.png differ diff --git a/emoji/dark.png b/emoji/dark.png new file mode 100644 index 000000000..775a77a1e Binary files /dev/null and b/emoji/dark.png differ diff --git a/emoji/dragon1.png b/emoji/dragon1.png new file mode 100644 index 000000000..07a5c4ec3 Binary files /dev/null and b/emoji/dragon1.png differ diff --git a/emoji/electric.png b/emoji/electric.png new file mode 100644 index 000000000..4094e36b0 Binary files /dev/null and b/emoji/electric.png differ diff --git a/emoji/fairy1.png b/emoji/fairy1.png new file mode 100644 index 000000000..745c7f1d3 Binary files /dev/null and b/emoji/fairy1.png differ diff --git a/emoji/fighting.png b/emoji/fighting.png new file mode 100644 index 000000000..64fe19612 Binary files /dev/null and b/emoji/fighting.png differ diff --git a/emoji/fire1.png b/emoji/fire1.png new file mode 100644 index 000000000..91a8d10f7 Binary files /dev/null and b/emoji/fire1.png differ diff --git a/emoji/flying.png b/emoji/flying.png new file mode 100644 index 000000000..c39c3fbbe Binary files /dev/null and b/emoji/flying.png differ diff --git a/emoji/ghost1.png b/emoji/ghost1.png new file mode 100644 index 000000000..e5e2f56b5 Binary files /dev/null and b/emoji/ghost1.png differ diff --git a/emoji/grass.png b/emoji/grass.png new file mode 100644 index 000000000..ebafb0738 Binary files /dev/null and b/emoji/grass.png differ diff --git a/emoji/ground.png b/emoji/ground.png new file mode 100644 index 000000000..3d006a6df Binary files /dev/null and b/emoji/ground.png differ diff --git a/emoji/here.png b/emoji/here.png new file mode 100644 index 000000000..2e9671214 Binary files /dev/null and b/emoji/here.png differ diff --git a/emoji/ice.png b/emoji/ice.png new file mode 100644 index 000000000..1c9102cb4 Binary files /dev/null and b/emoji/ice.png differ diff --git a/emoji/instinct.png b/emoji/instinct.png new file mode 100644 index 000000000..096e786f0 Binary files /dev/null and b/emoji/instinct.png differ diff --git a/emoji/mystic.png b/emoji/mystic.png new file mode 100644 index 000000000..850981892 Binary files /dev/null and b/emoji/mystic.png differ diff --git a/emoji/normal.png b/emoji/normal.png new file mode 100644 index 000000000..ebfed6652 Binary files /dev/null and b/emoji/normal.png differ diff --git a/emoji/omw.png b/emoji/omw.png new file mode 100644 index 000000000..d64ffa444 Binary files /dev/null and b/emoji/omw.png differ diff --git a/emoji/pkbtlr.png b/emoji/pkbtlr.png new file mode 100644 index 000000000..bf4c96d90 Binary files /dev/null and b/emoji/pkbtlr.png differ diff --git a/emoji/poison.png b/emoji/poison.png new file mode 100644 index 000000000..c23c4764e Binary files /dev/null and b/emoji/poison.png differ diff --git a/emoji/psychic.png b/emoji/psychic.png new file mode 100644 index 000000000..1c47d4873 Binary files /dev/null and b/emoji/psychic.png differ diff --git a/emoji/purified.png b/emoji/purified.png new file mode 100644 index 000000000..198132128 Binary files /dev/null and b/emoji/purified.png differ diff --git a/emoji/rock1.png b/emoji/rock1.png new file mode 100644 index 000000000..786958b89 Binary files /dev/null and b/emoji/rock1.png differ diff --git a/emoji/shadow.png b/emoji/shadow.png new file mode 100644 index 000000000..309a57420 Binary files /dev/null and b/emoji/shadow.png differ diff --git a/emoji/steel.png b/emoji/steel.png new file mode 100644 index 000000000..67ebd9fc0 Binary files /dev/null and b/emoji/steel.png differ diff --git a/emoji/valor.png b/emoji/valor.png new file mode 100644 index 000000000..40b320416 Binary files /dev/null and b/emoji/valor.png differ diff --git a/emoji/water.png b/emoji/water.png new file mode 100644 index 000000000..1e4b2be5b Binary files /dev/null and b/emoji/water.png differ diff --git a/entry-nopsql.sh b/entry-nopsql.sh new file mode 100644 index 000000000..52681b424 --- /dev/null +++ b/entry-nopsql.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +export PATH="/app/venv/bin:$PATH" && export PYTHONPATH=/app && exec nohup python3 /app/meowth/launcher.py -d diff --git a/entry.sh b/entry.sh new file mode 100644 index 000000000..a936f2a24 --- /dev/null +++ b/entry.sh @@ -0,0 +1,355 @@ +#!/usr/bin/env bash +set -Eeo pipefail +# TODO swap to -Eeuo pipefail above (after handling all potentially-unset variables) + +# usage: file_env VAR [DEFAULT] +# ie: file_env 'XYZ_DB_PASSWORD' 'example' +# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of +# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + printf >&2 'error: both %s and %s are set (but are exclusive)\n' "$var" "$fileVar" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +# check to see if this file is being run or sourced from another script +_is_sourced() { + # https://unix.stackexchange.com/a/215279 + [ "${#FUNCNAME[@]}" -ge 2 ] \ + && [ "${FUNCNAME[0]}" = '_is_sourced' ] \ + && [ "${FUNCNAME[1]}" = 'source' ] +} + +# used to create initial postgres directories and if run as root, ensure ownership to the "postgres" user +docker_create_db_directories() { + local user; user="$(id -u)" + + mkdir -p "$PGDATA" + # ignore failure since there are cases where we can't chmod (and PostgreSQL might fail later anyhow - it's picky about permissions of this directory) + chmod 00700 "$PGDATA" || : + + # ignore failure since it will be fine when using the image provided directory; see also https://github.com/docker-library/postgres/pull/289 + mkdir -p /var/run/postgresql || : + chmod 03775 /var/run/postgresql || : + + # Create the transaction log directory before initdb is run so the directory is owned by the correct user + if [ -n "${POSTGRES_INITDB_WALDIR:-}" ]; then + mkdir -p "$POSTGRES_INITDB_WALDIR" + if [ "$user" = '0' ]; then + find "$POSTGRES_INITDB_WALDIR" \! -user postgres -exec chown postgres '{}' + + fi + chmod 700 "$POSTGRES_INITDB_WALDIR" + fi + + # allow the container to be started with `--user` + if [ "$user" = '0' ]; then + find "$PGDATA" \! -user postgres -exec chown postgres '{}' + + find /var/run/postgresql \! -user postgres -exec chown postgres '{}' + + fi +} + +# initialize empty PGDATA directory with new database via 'initdb' +# arguments to `initdb` can be passed via POSTGRES_INITDB_ARGS or as arguments to this function +# `initdb` automatically creates the "postgres", "template0", and "template1" dbnames +# this is also where the database user is created, specified by `POSTGRES_USER` env +docker_init_database_dir() { + # "initdb" is particular about the current user existing in "/etc/passwd", so we use "nss_wrapper" to fake that if necessary + # see https://github.com/docker-library/postgres/pull/253, https://github.com/docker-library/postgres/issues/359, https://cwrap.org/nss_wrapper.html + local uid; uid="$(id -u)" + if ! getent passwd "$uid" &> /dev/null; then + # see if we can find a suitable "libnss_wrapper.so" (https://salsa.debian.org/sssd-team/nss-wrapper/-/commit/b9925a653a54e24d09d9b498a2d913729f7abb15) + local wrapper + for wrapper in {/usr,}/lib{/*,}/libnss_wrapper.so; do + if [ -s "$wrapper" ]; then + NSS_WRAPPER_PASSWD="$(mktemp)" + NSS_WRAPPER_GROUP="$(mktemp)" + export LD_PRELOAD="$wrapper" NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP + local gid; gid="$(id -g)" + printf 'postgres:x:%s:%s:PostgreSQL:%s:/bin/false\n' "$uid" "$gid" "$PGDATA" > "$NSS_WRAPPER_PASSWD" + printf 'postgres:x:%s:\n' "$gid" > "$NSS_WRAPPER_GROUP" + break + fi + done + fi + + if [ -n "${POSTGRES_INITDB_WALDIR:-}" ]; then + set -- --waldir "$POSTGRES_INITDB_WALDIR" "$@" + fi + + # --pwfile refuses to handle a properly-empty file (hence the "\n"): https://github.com/docker-library/postgres/issues/1025 + eval 'initdb --username="$POSTGRES_USER" --pwfile=<(printf "%s\n" "$POSTGRES_PASSWORD") '"$POSTGRES_INITDB_ARGS"' "$@"' + + # unset/cleanup "nss_wrapper" bits + if [[ "${LD_PRELOAD:-}" == */libnss_wrapper.so ]]; then + rm -f "$NSS_WRAPPER_PASSWD" "$NSS_WRAPPER_GROUP" + unset LD_PRELOAD NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP + fi +} + +# print large warning if POSTGRES_PASSWORD is long +# error if both POSTGRES_PASSWORD is empty and POSTGRES_HOST_AUTH_METHOD is not 'trust' +# print large warning if POSTGRES_HOST_AUTH_METHOD is set to 'trust' +# assumes database is not set up, ie: [ -z "$DATABASE_ALREADY_EXISTS" ] +docker_verify_minimum_env() { + # check password first so we can output the warning before postgres + # messes it up + if [ "${#POSTGRES_PASSWORD}" -ge 100 ]; then + cat >&2 <<-'EOWARN' + + WARNING: The supplied POSTGRES_PASSWORD is 100+ characters. + + This will not work if used via PGPASSWORD with "psql". + + https://www.postgresql.org/message-id/flat/E1Rqxp2-0004Qt-PL%40wrigleys.postgresql.org (BUG #6412) + https://github.com/docker-library/postgres/issues/507 + + EOWARN + fi + if [ -z "$POSTGRES_PASSWORD" ] && [ 'trust' != "$POSTGRES_HOST_AUTH_METHOD" ]; then + # The - option suppresses leading tabs but *not* spaces. :) + cat >&2 <<-'EOE' + Error: Database is uninitialized and superuser password is not specified. + You must specify POSTGRES_PASSWORD to a non-empty value for the + superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run". + + You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all + connections without a password. This is *not* recommended. + + See PostgreSQL documentation about "trust": + https://www.postgresql.org/docs/current/auth-trust.html + EOE + exit 1 + fi + if [ 'trust' = "$POSTGRES_HOST_AUTH_METHOD" ]; then + cat >&2 <<-'EOWARN' + ******************************************************************************** + WARNING: POSTGRES_HOST_AUTH_METHOD has been set to "trust". This will allow + anyone with access to the Postgres port to access your database without + a password, even if POSTGRES_PASSWORD is set. See PostgreSQL + documentation about "trust": + https://www.postgresql.org/docs/current/auth-trust.html + In Docker's default configuration, this is effectively any other + container on the same system. + + It is not recommended to use POSTGRES_HOST_AUTH_METHOD=trust. Replace + it with "-e POSTGRES_PASSWORD=password" instead to set a password in + "docker run". + ******************************************************************************** + EOWARN + fi +} + +# usage: docker_process_init_files [file [file [...]]] +# ie: docker_process_init_files /always-initdb.d/* +# process initializer files, based on file extensions and permissions +docker_process_init_files() { + # psql here for backwards compatibility "${psql[@]}" + psql=( docker_process_sql ) + + printf '\n' + local f + for f; do + case "$f" in + *.sh) + # https://github.com/docker-library/postgres/issues/450#issuecomment-393167936 + # https://github.com/docker-library/postgres/pull/452 + if [ -x "$f" ]; then + printf '%s: running %s\n' "$0" "$f" + "$f" + else + printf '%s: sourcing %s\n' "$0" "$f" + . "$f" + fi + ;; + *.sql) printf '%s: running %s\n' "$0" "$f"; docker_process_sql -f "$f"; printf '\n' ;; + *.sql.gz) printf '%s: running %s\n' "$0" "$f"; gunzip -c "$f" | docker_process_sql; printf '\n' ;; + *.sql.xz) printf '%s: running %s\n' "$0" "$f"; xzcat "$f" | docker_process_sql; printf '\n' ;; + *.sql.zst) printf '%s: running %s\n' "$0" "$f"; zstd -dc "$f" | docker_process_sql; printf '\n' ;; + *) printf '%s: ignoring %s\n' "$0" "$f" ;; + esac + printf '\n' + done +} + +# Execute sql script, passed via stdin (or -f flag of pqsl) +# usage: docker_process_sql [psql-cli-args] +# ie: docker_process_sql --dbname=mydb <<<'INSERT ...' +# ie: docker_process_sql -f my-file.sql +# ie: docker_process_sql > "$PGDATA/pg_hba.conf" +} + +# start socket-only postgresql server for setting up or running scripts +# all arguments will be passed along as arguments to `postgres` (via pg_ctl) +docker_temp_server_start() { + if [ "$1" = 'postgres' ]; then + shift + fi + + # internal start of server in order to allow setup using psql client + # does not listen on external TCP/IP and waits until start finishes + set -- "$@" -c listen_addresses='' -p "${PGPORT:-5432}" + + PGUSER="${PGUSER:-$POSTGRES_USER}" \ + pg_ctl -D "$PGDATA" \ + -o "$(printf '%q ' "$@")" \ + -w start +} + +# stop postgresql server after done setting up user and running scripts +docker_temp_server_stop() { + PGUSER="${PGUSER:-postgres}" \ + pg_ctl -D "$PGDATA" -m fast -w stop +} + +# check arguments for an option that would cause postgres to stop +# return true if there is one +_pg_want_help() { + local arg + for arg; do + case "$arg" in + # postgres --help | grep 'then exit' + # leaving out -C on purpose since it always fails and is unhelpful: + # postgres: could not access the server configuration file "/var/lib/postgresql/data/postgresql.conf": No such file or directory + -'?'|--help|--describe-config|-V|--version) + return 0 + ;; + esac + done + return 1 +} + +_main() { + # if first arg looks like a flag, assume we want to run postgres server + if [ "${1:0:1}" = '-' ]; then + set -- postgres "$@" + fi + + if [ "$1" = 'postgres' ] && ! _pg_want_help "$@"; then + docker_setup_env + # setup data directories and permissions (when run as root) + docker_create_db_directories + if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" + fi + + # only run initialization on an empty data directory + if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + + printf '%s: running %s\n' "$0" "/app/database/schema.sql"; docker_process_sql -f /app/database/schema.sql; printf '\n' + sudo mv /app/database/schema.sql /app/database/schema.bak + printf '%s: running %s\n' "$0" "/app/database/pokemon.sql"; PGHOST= PGHOSTADDR= pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" /app/database/pokemon.sql; printf '\n' + sudo mv /app/database/pokemon.sql /app/database/pokemon.bak + sudo mv /app/database/* /docker-entrypoint-initdb.d/ + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD + + cat <<-'EOM' + PostgreSQL init process complete; ready for start up. + EOM + + else + cat <<-'EOM' + PostgreSQL Database directory appears to contain a database; Skipping initialization + EOM + fi + fi + + nohup sudo -- bash -c 'export PATH="/app/venv/bin:$PATH" && export PYTHONPATH=/app && python3 /app/meowth/launcher.py -d' & + exec "$@" +} + +if ! _is_sourced; then + _main "$@" +fi \ No newline at end of file diff --git a/meowth/__main__.py b/meowth/__main__.py index 022fe43ee..23fbab2c4 100644 --- a/meowth/__main__.py +++ b/meowth/__main__.py @@ -13,9 +13,6 @@ import argparse import asyncio import sys -import os -from multiprocessing import Pool -from functools import partial import discord @@ -86,7 +83,7 @@ def parse_cli_args(): def main(): args = parse_cli_args() - run_bot(debug=args.debug, launcher=args.launcher, + run_bot(debug=args.debug, launcher=args.launcher, from_restart=args.fromrestart) diff --git a/meowth/config_template.py b/meowth/config_template.py deleted file mode 100644 index f07636ecd..000000000 --- a/meowth/config_template.py +++ /dev/null @@ -1,119 +0,0 @@ -'''Configuration values for Meowth - Rename to config.py''' - -# bot token from discord developers -bot_token = 'your_token_here' - -# default bot settings -bot_prefix = '!' -bot_master = 12345678903216549878 -bot_coowners = [132314336914833409, 263607303096369152] -preload_extensions = [] -version = '3' - -# minimum required permissions for bot user -bot_permissions = 268822736 - -# postgresql database credentials -db_details = { - # 'username' : 'meowth', - # 'database' : 'meowth', - # 'hostname' : 'localhost', - 'password' : 'password' -} - -dbdocid = 'google_sheet_id_here' - -emoji = { - 'maybe': '🙋', - 'coming': '🚗', - 'here': '<:here:350686955316445185>', - 'remote': '🛰', - 'invite': '✉', - 'cancel': '❌' -} - -# default language -lang_bot = 'en' -lang_pkmn = 'en' - -# team settings -team_list = ['mystic', 'valor', 'instinct'] -team_colours = { - "mystic" : "0x3498db", - "valor" : "0xe74c3c", - "instinct" : "0xf1c40f" -} - -team_emoji = { - "mystic" : "<:mystic:351758303912656896>", - "valor" : "<:valor:351758298975830016>", - "instinct" : "<:instinct:351758298627702786>", - "unknown" : "\u2754" -} - -# raid settings -allow_assume = { - "5" : "False", - "4" : "False", - "3" : "False", - "2" : "False", - "1" : "False" -} - -status_emoji = { - "omw" : ":omw:", - "here_id" : ":here:" -} - -type_emoji = { - "normal" : "<:normal:351758296409178112>", - "fire" : "<:fire1:351758296044142624>", - "water" : "<:water:351758295142498325>", - "electric" : "<:electric:351758295414865921>", - "grass" : "<:grass:351758295729700868>", - "ice" : "<:ice:351758296111120384>", - "fighting" : "<:fighting:351758296090148864>", - "poison" : "<:poison:351758295976902679>", - "ground" : "<:ground:351758295968776194>", - "flying" : "<:flying:351758295033446400>", - "psychic" : "<:psychic:351758294744039426>", - "bug" : "<:bug1:351758295196893185>", - "rock" : "<:rock:351758296077697024>", - "ghost" : "<:ghost1:351758295683432449>", - "dragon" : "<:dragon:351758295612129280>", - "dark" : "<:dark:351758294316089356>", - "steel" : "<:steel:351758296425955328>", - "fairy" : "<:fairy:351758295070932992>" -} - -raid_times = { - 1: (60, 45), - 2: (60, 45), - 3: (60, 45), - 4: (60, 45), - 5: (60, 45), - "EX": (None, 45) -} - -# weatherapikey = - -max_report_distance = 20 - -# help command categories -command_categories = { - "Owner" : { - "index" : "5", - "description" : "Owner-only commands for bot config or info." - }, - "Server Config" : { - "index" : "10", - "description" : "Server configuration commands." - }, - "Bot Info" : { - "index" : "15", - "description" : "Commands for finding out information on the bot." - }, -} - -# analytics/statistics -pokebattler_tracker = "MeowthSelfHoster" diff --git a/meowth/core/bot.py b/meowth/core/bot.py index df627f310..c07707912 100644 --- a/meowth/core/bot.py +++ b/meowth/core/bot.py @@ -152,7 +152,7 @@ async def shutdown(self, *, restart=False): @cached_property def invite_url(self): invite_url = discord.utils.oauth_url(self.user.id, - permissions=self.req_perms) + permissions=self.req_perms).replace("+application.commands","") return invite_url @property @@ -172,19 +172,19 @@ def uptime_str(self): uptime = self.uptime year_str, month_str, day_str, hour_str = ('',)*4 if uptime.years >= 1: - year_str = "{0}y ".format(uptime.years) + year_str = f"{uptime.years}y " if uptime.months >= 1 or year_str: - month_str = "{0}m ".format(uptime.months) + month_str = f"{uptime.months}m " if uptime.days >= 1 or month_str: d_unit = 'd' if month_str else ' days' - day_str = "{0}{1} ".format(uptime.days, d_unit) + day_str = f"{uptime.days}{d_unit} " if uptime.hours >= 1 or day_str: h_unit = ':' if month_str else ' hrs' - hour_str = "{0}{1}".format(uptime.hours, h_unit) + hour_str = f"{uptime.hours}{h_unit}" m_unit = '' if month_str else ' mins' - mins = uptime.minutes if month_str else ' {0}'.format(uptime.minutes) - secs = '' if day_str else ' {0} secs'.format(uptime.seconds) - min_str = "{0}{1}{2}".format(mins, m_unit, secs) + mins = uptime.minutes if month_str else f" {uptime.minutes}" + secs = '' if day_str else f" {uptime.seconds} secs" + min_str = f"{mins}{m_unit}{secs}" uptime_str = ''.join((year_str, month_str, day_str, hour_str, min_str)) @@ -292,11 +292,11 @@ async def on_guild_join(self, guild): } insert.row(**d) await insert.commit(do_update=True) - + async def on_message(self, message): self.counter["messages_read"] += 1 await self.process_commands(message) - + async def wait_for(self, event, /, *, check=None, timeout=None): result = await super().wait_for(event, check=check, timeout=timeout) if event == "message": @@ -323,7 +323,7 @@ async def on_shard_ready(self, shard_id): async def on_ready(self): intro = "Meowth - Discord bot for Pokemon Go Communities" - intro_deco = "{0}\n{1}\n{0}".format('='*len(intro), intro) + intro_deco = f"{'='*len(intro)}\n{intro}\n{'='*len(intro)}" if not self.launch_time: self.launch_time = datetime.utcnow() if not self.launcher: @@ -346,10 +346,10 @@ async def on_ready(self): print("I'm not in any server yet, so be sure to invite me!") if self.invite_url: print(f"\nInvite URL: {self.invite_url}\n") - + # load extensions marked for preload in config for ext in self.preload_ext: - ext_name = ("meowth.exts."+ext) + ext_name = "meowth.exts."+ext self.load_extension(ext_name) if self.from_restart: diff --git a/meowth/core/cog_base.py b/meowth/core/cog_base.py index 24a816313..e3cc5472b 100644 --- a/meowth/core/cog_base.py +++ b/meowth/core/cog_base.py @@ -1,9 +1,8 @@ import importlib import logging -from meowth.utils import Map from discord.ext.commands import Cog - +from meowth.utils import Map class Cog(Cog): """Base Class for Cogs to inherit in order to automate Cog setup. @@ -66,10 +65,10 @@ async def _table_setup(self, table_module): for table in self.tables.values(): if await table.exists(): self.logger.info( - f'Cog table {table.name} for {cog_name} found.') + "Cog table %s for %s found.", table.name, cog_name) table.new_columns = [] table.initial_data = [] continue await table.create() - self.logger.info(f'Cog table {table.name} for {cog_name} created.') + self.logger.info("Cog table %s for %s created.", table.name, cog_name) del table_module diff --git a/meowth/core/cog_manager.py b/meowth/core/cog_manager.py index eb754969c..02cc38b2b 100644 --- a/meowth/core/cog_manager.py +++ b/meowth/core/cog_manager.py @@ -95,13 +95,13 @@ async def load(self, ctx, *extensions): async def _core(self, ctx): """Reload Core Commands.""" await self.load_extension( - ctx, 'Core Commands', f'meowth.core.commands') + ctx, 'Core Commands', 'meowth.core.commands') @load.command(name="cm") async def _cm(self, ctx): """Reload Cog Manager.""" await self.load_extension( - ctx, 'Cog Manager', f'meowth.core.cog_manager') + ctx, 'Cog Manager', 'meowth.core.cog_manager') @command(category='Owner', name='reload', aliases=['load']) async def _reload(self, ctx, *, cogs): diff --git a/meowth/core/commands.py b/meowth/core/commands.py index 493563c5f..6ec368bf6 100644 --- a/meowth/core/commands.py +++ b/meowth/core/commands.py @@ -118,7 +118,7 @@ async def status(self, ctx, *, status: str): activity=game) embed = make_embed( msg_type='success', - title="Status changed to {}.".format(status)) + title=f"Status changed to {status}.") await ctx.send(embed=embed) @_set.command(name="username", aliases=["name"]) @@ -131,9 +131,9 @@ async def _username(self, ctx, *, username: str): embed = make_embed( msg_type='error', title="Failed to change name", - content=("Remember that you can only do it up to 2 times an " + content="Remember that you can only do it up to 2 times an " "hour. Use nicknames if you need frequent changes. " - "**{}set nickname**").format(ctx.prefix)) + f"**{ctx.prefix}set nickname**") await ctx.send(embed=embed) else: embed = make_embed(msg_type='success', title="Username set.") @@ -165,9 +165,8 @@ async def _nickname(self, ctx, *, nickname: str): embed = make_embed( msg_type='error', title="Failed to set nickname", - content=("I'm missing permissions to change my nickname. " - "Use **{}get guildperms** to check permissions." - "").format(ctx.prefix)) + content="I'm missing permissions to change my nickname. " + f"Use **{ctx.prefix}get guildperms** to check permissions.") await ctx.send() else: embed = make_embed(msg_type='success', title="Nickname set.") @@ -179,16 +178,16 @@ async def _uptime(self, ctx): uptime_str = ctx.bot.uptime_str try: await ctx.embed('Uptime', uptime_str, colour='blue', - icon="https://i.imgur.com/82Cqf1x.png") + icon="https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/uptime.png") except discord.errors.Forbidden: - await ctx.send("Uptime: {}".format(uptime_str)) + await ctx.send(f"Uptime: {uptime_str}") @command(name="botinvite", category='Bot Info') async def _bot_invite(self, ctx, plain_url: bool = False): """Shows bot's invite url""" - invite_url = ctx.bot.invite_url + invite_url = ctx.bot.invite_url.replace("+application.commands","") if plain_url: - await ctx.send("Invite URL: <{}>".format(invite_url)) + await ctx.send(f"Invite URL: <{invite_url}>") return else: embed = make_embed( @@ -199,7 +198,7 @@ async def _bot_invite(self, ctx, plain_url: bool = False): try: await ctx.send(embed=embed) except discord.errors.Forbidden: - await ctx.send("Invite URL: <{}>".format(invite_url)) + await ctx.send(f"Invite URL: <{invite_url}>") @command(name="about", category='Bot Info') async def _about(self, ctx): @@ -209,7 +208,7 @@ async def _about(self, ctx): bot_repo = author_repo + "/Meowth" uptime_str = bot.uptime_str owner = await ctx.get.user(ctx.bot.owner) - invite_str = "[Invite Me!]({})".format(bot.invite_url) + invite_str = f"[Invite Me!]({bot.invite_url})" if ctx.guild: prefix = bot.prefixes.get(ctx.guild.id, bot.default_prefix) @@ -235,7 +234,7 @@ async def _about(self, ctx): # embed_colour = await url_color(bot.avatar_small) embed = make_embed( icon=bot.avatar_small, title=f"{bot.user}", - content='\n'.join(about), + content='\n'.join(about), # msg_colour=embed_colour ) embed.set_thumbnail(url=bot.avatar) @@ -253,7 +252,7 @@ def get_cpu(self): async def _stats(self, ctx): """Shows stats about bot""" bot = ctx.bot - owner = await bot.get_user_info(ctx.bot.owner) + owner = bot.get_user(ctx.bot.owner_id) uptime_str = bot.uptime_str cpu_p = await ctx.bot.loop.run_in_executor(None, self.get_cpu) mem = psutil.virtual_memory() @@ -269,13 +268,15 @@ async def _stats(self, ctx): 'MB':1048576, 'GB':1073741824 } + + p_mem_str = "" + swap_str = "" + for size, value in data_sizes.items(): if (p_mem / value) > 1 < 1024: - p_mem_str = "{} {}".format( - round(p_mem / value, 2), size) + p_mem_str = f"{round(p_mem / value, 2)} {size}" if (swapped / value) > 1 < 1024: - swap_str = "{} {}".format( - round(swapped / value, 2), size) + swap_str = f"{round(swapped / value, 2)} {size}" member_count = 0 server_count = 0 @@ -418,9 +419,9 @@ async def guild_perms(self, ctx, guild_id=None): for perm, bitshift in perm_dict.items(): if bool((req_perms.value >> bitshift) & 1): if bool((guild_perms.value >> bitshift) & 1): - msg += ":white_small_square: {}\n".format(perm) + msg += f":white_small_square: {perm}\n" else: - msg += ":black_small_square: {}\n".format(perm) + msg += f":black_small_square: {perm}\n" try: if not isinstance(ctx.channel, discord.DMChannel): @@ -506,8 +507,7 @@ async def _ping(self, ctx): msg = '' for shard, latency in ctx.bot.latencies: here = ' 🡸' if shard == ctx.guild.shard_id else '' - msg += ("**Shard {0}:** {1:.2f} ms{2}" - "\n").format(shard, latency * 1000, here) + msg += f"**Shard {shard}:** {latency * 1000:.2f} ms{here}\n" await ctx.embed('Latency', msg, msg_type='info') @command() @@ -529,8 +529,7 @@ def is_unpinned(m): deleted = await ctx.channel.purge(limit=msg_number, check=is_unpinned) embed = make_embed( msg_type='success', - title='Deleted {} message{}'.format( - len(deleted), "s" if len(deleted) > 1 else "")) + title=f'Deleted {len(deleted)} message{"s" if len(deleted) > 1 else ""}') result_msg = await ctx.send(embed=embed) await asyncio.sleep(3) await result_msg.delete() @@ -547,7 +546,7 @@ async def reload_cm(self, ctx): title='Cog Manager reloaded.') await ctx.send(embed=embed) except Exception as e: - msg = "{}: {}".format(type(e).__name__, e) + msg = f"{type(e).__name__}: {e}" embed = make_embed(msg_type='error', title='Error loading Cog Manager', content=msg) @@ -565,7 +564,7 @@ async def _prefix(self, ctx, *, new_prefix: str = None): if new_prefix: embed = make_embed( msg_type='error', - title=f"Prefix can only be changed in guilds.") + title="Prefix can only be changed in guilds.") await ctx.send(embed=embed) else: embed = make_embed( @@ -609,11 +608,10 @@ async def _help(self, ctx, *, command_name: str = None): await p.paginate() except Exception as e: await ctx.send(e) - + @command(name='list') async def _list(self, ctx, *args): """Base command for listing reports or RSVPs.""" - pass # @group(category='Server Config', name='enable', aliases=['disable'], # invoke_without_command=True, hidden=True) @@ -664,6 +662,5 @@ async def _list(self, ctx, *args): # msg_type='info', title='Available Cogs', content=cog_msg) # await ctx.send(embed=embed) - def setup(bot): bot.add_cog(Core(bot)) diff --git a/meowth/core/context.py b/meowth/core/context.py index 47bc69421..ff64c1be4 100644 --- a/meowth/core/context.py +++ b/meowth/core/context.py @@ -1,6 +1,6 @@ import asyncio import textwrap -import gettext +import builtins from aiocontextvars import ContextVar @@ -14,7 +14,6 @@ cvar = ContextVar('bot') def ctx_setup(loop): - import builtins builtins.__dict__['_'] = use_current_gettext builtins.__dict__['get_ctx'] = cvar.get builtins.__dict__['__cvar__'] = cvar @@ -283,7 +282,7 @@ def check(emoji, message_id, channel_id, user_id): finally: if autodelete: await msg.delete() - + async def tz(self): if hasattr(self, '_tz'): return self._tz @@ -292,7 +291,7 @@ async def tz(self): query.where(channelid=self.channel.id) zone = await query.get_value() return zone - + async def version(self): if not self.guild: return None @@ -345,7 +344,7 @@ async def user(self, search_term): member = members.get(search_term, None) return member - async def message(self, id, channel=None, guild=None, no_cache=False): + async def message(self, message_id, channel=None, guild=None, no_cache=False): """Get a message from the current or specified channels. Parameters @@ -371,11 +370,11 @@ async def message(self, id, channel=None, guild=None, no_cache=False): return None channel = channel or self.ctx.channel if not no_cache: - msg = self.get(channel._state._messages, id=id) + msg = self.get(channel._state._messages, id=message_id) if msg: return msg try: - return await channel.fetch_message(id) + return await channel.fetch_message(message_id) except discord.NotFound: return None @@ -520,7 +519,6 @@ def member(self, search_term, guild=None): if isinstance(search_term, int): member = guild.get_member(search_term) if not member: - # TODO pass return member if isinstance(search_term, str): diff --git a/meowth/core/data_manager/dbi.py b/meowth/core/data_manager/dbi.py index 4172eb8ec..d2f96a341 100644 --- a/meowth/core/data_manager/dbi.py +++ b/meowth/core/data_manager/dbi.py @@ -25,8 +25,7 @@ def __init__(self, database="meowth", port=5432): self.loop = None - self.dsn = "postgres://{}:{}@{}:{}/{}".format( - username, password, hostname, port, database) + self.dsn = f"postgres://{username}:{password}@{hostname}:{port}/{database}" self.pool = None self.settings_conn = None self.settings_stmt = None @@ -42,10 +41,10 @@ async def start(self, loop=None): self.pool = await asyncpg.create_pool( self.dsn, loop=loop, init=init_conn) await self.prepare() - + async def recreate_pool(self): - logger.warning(f'Re-creating closed database pool.') + logger.warning('Re-creating closed database pool.') self.pool = await asyncpg.create_pool( self.dsn, loop=self.loop, init=init_conn) @@ -67,9 +66,9 @@ async def core_tables_exist(self): for k, v in core_sql.items(): table_exists = await self.table(k).exists() if not table_exists: - logger.warning(f'Core table {k} not found. Creating...') + logger.warning("Core table %s not found. Creating...", k) await self.execute_transaction(v) - logger.warning(f'Core table {k} created.') + logger.warning("Core table %s created.", k) async def stop(self): conns = (self.settings_conn, self.listener_conn) @@ -102,7 +101,7 @@ async def execute_query(self, query, *query_args): result.append(rcrd) return result except asyncpg.exceptions.InterfaceError as e: - logger.error(f'Exception {type(e)}: {e}') + logger.error("Exception %s: %s", type(e), e) await self.recreate_pool() return await self.execute_query(query, *query_args) @@ -123,10 +122,10 @@ async def execute_transaction(self, query, *query_args): result.append(rcrd) return result except asyncpg.exceptions.InterfaceError as e: - logger.error(f'Exception {type(e)}: {e}') + logger.error("Exception %s: %s", type(e), e) await self.recreate_pool() return await self.execute_transaction(query, *query_args) - + async def add_listeners(self, *listeners): con = self.listener_conn for listener in listeners: @@ -135,7 +134,7 @@ async def add_listeners(self, *listeners): self.listeners.append(listener) await con.add_listener(listener[0], listener[1]) return - + async def remove_listeners(self, *listeners): con = self.listener_conn for listener in listeners: @@ -168,6 +167,6 @@ async def tables(self): table.query.where(table_schema='public') table.query.order_by('table_name') return await table.query.get() - + def schema(self, name): return Schema(self, name) diff --git a/meowth/core/data_manager/schema.py b/meowth/core/data_manager/schema.py index 9b68e76cc..773a8dce7 100644 --- a/meowth/core/data_manager/schema.py +++ b/meowth/core/data_manager/schema.py @@ -1,7 +1,7 @@ from itertools import zip_longest, chain from more_itertools import partition -from .errors import PostgresError, SchemaError, ResponseError, QueryError +from .errors import SchemaError, ResponseError, QueryError from . import sqltypes class SQLOperator: @@ -67,7 +67,7 @@ def between(cls): @classmethod def in_(cls): return cls('=', 'in', '{column} {operator} any({value})') - + @classmethod def contains_(cls): return cls('=', 'in', '{value} {operator} any({column})') @@ -75,11 +75,11 @@ def contains_(cls): @classmethod def is_(cls): return cls('IS', 'is', cls.default_template) - + @classmethod def isnot_(cls): return cls('IS NOT', 'is not', cls.default_template) - + @classmethod def notnull_(cls): return cls('IS NOT NULL', 'is not None', '{column} {operator}') @@ -149,44 +149,34 @@ def __str__(self): return self.full_name def __lt__(self, value): - return SQLComparison( - SQLOperator.lt(), self.aggregate, self.full_name, value) + return SQLComparison(SQLOperator.lt(), self.aggregate, self.full_name, value) def __le__(self, value): - return SQLComparison( - SQLOperator.le(), self.aggregate, self.full_name, value) + return SQLComparison(SQLOperator.le(), self.aggregate, self.full_name, value) def __eq__(self, value): - return SQLComparison( - SQLOperator.eq(), self.aggregate, self.full_name, value) + return SQLComparison(SQLOperator.eq(), self.aggregate, self.full_name, value) def __ne__(self, value): - return SQLComparison( - SQLOperator.ne(), self.aggregate, self.full_name, value) + return SQLComparison(SQLOperator.ne(), self.aggregate, self.full_name, value) def __gt__(self, value): - return SQLComparison( - SQLOperator.gt(), self.aggregate, self.full_name, value) + return SQLComparison(SQLOperator.gt(), self.aggregate, self.full_name, value) def __ge__(self, value): - return SQLComparison( - SQLOperator.ge(), self.aggregate, self.full_name, value) + return SQLComparison(SQLOperator.ge(), self.aggregate, self.full_name, value) def like(self, value): - return SQLComparison( - SQLOperator.like(), self.aggregate, self.full_name, value) + return SQLComparison(SQLOperator.like(), self.aggregate, self.full_name, value) def ilike(self, value): - return SQLComparison( - SQLOperator.ilike(), self.aggregate, self.full_name, value) + return SQLComparison(SQLOperator.ilike(), self.aggregate, self.full_name, value) def not_like(self, value): - return SQLComparison( - SQLOperator.not_like(), self.aggregate, self.full_name, value) + return SQLComparison(SQLOperator.not_like(), self.aggregate, self.full_name, value) def not_ilike(self, value): - return SQLComparison( - SQLOperator.not_ilike(), self.aggregate, self.full_name, value) + return SQLComparison(SQLOperator.not_ilike(), self.aggregate, self.full_name, value) def between(self, minvalue, maxvalue): return SQLComparison( @@ -194,24 +184,19 @@ def between(self, minvalue, maxvalue): minvalue=minvalue, maxvalue=maxvalue) def in_(self, value): - return SQLComparison( - SQLOperator.in_(), self.aggregate, self.full_name, value) - + return SQLComparison(SQLOperator.in_(), self.aggregate, self.full_name, value) + def contains_(self, value): - return SQLComparison( - SQLOperator.contains_(), self.aggregate, self.full_name, value) - + return SQLComparison(SQLOperator.contains_(), self.aggregate, self.full_name, value) + def is_(self, value): - return SQLComparison( - SQLOperator.is_(), self.aggregate, self.full_name, value) - + return SQLComparison(SQLOperator.is_(), self.aggregate, self.full_name, value) + def isnot_(self, value): - return SQLComparison( - SQLOperator.isnot_(), self.aggregate, self.full_name, value) - + return SQLComparison(SQLOperator.isnot_(), self.aggregate, self.full_name, value) + def notnull_(self): - return SQLComparison( - SQLOperator.notnull_(), self.aggregate, self.full_name) + return SQLComparison(SQLOperator.notnull_(), self.aggregate, self.full_name) @classmethod def from_dict(cls, data): @@ -462,7 +447,7 @@ async def exists(self): async def drop(self): """Drop table from database.""" - sql = f"DROP TABLE $1" + sql = "DROP TABLE $1" return await self.dbi.execute_transaction(sql, (self.full_name,)) async def get_constraints(self): @@ -793,14 +778,14 @@ def sql(self, do_update=None): # handle conflict if required if do_update: - const_str = ', '.join(self._primaries) - sql += f" ON CONFLICT ({const_str}) DO UPDATE SET " + constraint_name=f"{self._from}_pkey" + sql += f" ON CONFLICT ON CONSTRAINT {constraint_name} DO UPDATE SET " excluded = [f'{c} = excluded.{c}' for c in cols] sql += ', '.join(excluded) if do_update is False: - const_str = ', '.join(self._primaries) - sql += f" ON CONFLICT ({const_str}) DO NOTHING" + constraint_name=f"{self._from}_pkey" + sql += f" ON CONFLICT ON CONSTRAINT {constraint_name} DO NOTHING" # add the returning statement if specified if self._returning: diff --git a/meowth/core/data_manager/sqltypes.py b/meowth/core/data_manager/sqltypes.py index d56535ee6..effd42480 100644 --- a/meowth/core/data_manager/sqltypes.py +++ b/meowth/core/data_manager/sqltypes.py @@ -3,7 +3,6 @@ import decimal from .errors import SchemaError - class SQLType: python = None @@ -38,21 +37,18 @@ def to_sql(self): def is_real_type(self): return True - class BooleanSQL(SQLType): python = bool def to_sql(self): return 'BOOLEAN' - class DateSQL(SQLType): python = datetime.date def to_sql(self): return 'DATE' - class DatetimeSQL(SQLType): python = datetime.datetime @@ -64,21 +60,18 @@ def to_sql(self): return 'TIMESTAMP WITH TIMEZONE' return 'TIMESTAMP' - class DoubleSQL(SQLType): python = float def to_sql(self): return 'REAL' - class FloatSQL(SQLType): python = float def to_sql(self): return 'FLOAT' - class IntegerSQL(SQLType): python = int @@ -106,7 +99,6 @@ def to_sql(self): def is_real_type(self): return not self.auto_increment - class IntervalSQL(SQLType): python = datetime.timedelta valid_fields = ( @@ -128,7 +120,6 @@ def to_sql(self): return 'INTERVAL ' + self.field return 'INTERVAL' - class DecimalSQL(SQLType): python = decimal.Decimal @@ -148,14 +139,12 @@ def to_sql(self): return f'NUMERIC({self.precision}, {self.scale})' return 'NUMERIC' - class StringSQL(SQLType): python = str def to_sql(self): return 'TEXT' - class TimeSQL(SQLType): python = datetime.time @@ -167,7 +156,6 @@ def to_sql(self): return 'TIME WITH TIME ZONE' return 'TIME' - class JSONSQL(SQLType): python = None diff --git a/meowth/core/data_manager/tables.py b/meowth/core/data_manager/tables.py index 22b28717c..41f480a60 100644 --- a/meowth/core/data_manager/tables.py +++ b/meowth/core/data_manager/tables.py @@ -3,29 +3,29 @@ def core_table_sqls(): sql_dict = { - 'guild_config' : ("CREATE TABLE guild_config (" + 'guild_config' : ("CREATE TABLE IF NOT EXISTS guild_config (" "guild_id bigint NOT NULL, " "config_name text NOT NULL, " "config_value text NOT NULL, " - "CONSTRAINT guild_config_pk " + "CONSTRAINT guild_config_pkey, " "PRIMARY KEY (guild_id, config_name));"), - 'restart_savedata' : ("CREATE TABLE restart_savedata (" + 'restart_savedata' : ("CREATE TABLE IF NOT EXISTS restart_savedata (" "restart_snowflake bigint NOT NULL, " "restart_by bigint NOT NULL, " "restart_channel bigint NOT NULL, " "restart_guild bigint, " "restart_message bigint, " - "CONSTRAINT restart_savedata_pk " + "CONSTRAINT restart_savedata_pkey, " "PRIMARY KEY (restart_snowflake));"), - 'prefixes' : ("CREATE TABLE prefix (" + 'prefixes' : ("CREATE TABLE IF NOT EXISTS prefix (" "guild_id bigint NOT NULL, " "prefix text NOT NULL, " - "CONSTRAINT prefixes_pkey " + "CONSTRAINT prefixes_pkey, " "PRIMARY KEY (guild_id));"), - 'discord_messages' : ("CREATE TABLE discord_messages (" + 'discord_messages' : ("CREATE TABLE IF NOT EXISTS discord_messages (" "message_id bigint NOT NULL, " "sent bigint NOT NULL, " "is_edit bool NOT NULL DEFAULT FALSE, " @@ -38,10 +38,10 @@ def core_table_sqls(): "embeds jsonb[], " "webhook_id bigint, " "attachments text[], " - "CONSTRAINT discord_messages_pkey " + "CONSTRAINT discord_messages_pkey, " "PRIMARY KEY (message_id, sent));"), - 'command_log' : ("CREATE TABLE command_log (" + 'command_log' : ("CREATE TABLE IF NOT EXISTS command_log (" "message_id bigint NOT NULL, " "sent bigint NOT NULL, " "author_id bigint NOT NULL, " @@ -54,11 +54,11 @@ def core_table_sqls(): "subcommand_passed text, " "command_failed bool NOT NULL DEFAULT FALSE, " "cog text, " - "CONSTRAINT command_log_pkey " + "CONSTRAINT command_log_pkey, " "PRIMARY KEY (message_id, sent));") } - log_sql = ("CREATE TABLE {log_table} (" + log_sql = ("CREATE TABLE IF NOT EXISTS {log_table} (" "log_id bigint NOT NULL, " "created bigint NOT NULL, " "logger_name text, " @@ -69,7 +69,7 @@ def core_table_sqls(): "line_no int, " "message text, " "traceback text, " - "CONSTRAINT {log_table}_pkey " + "CONSTRAINT {log_table}_pkey, " "PRIMARY KEY (log_id));") for log in LOGGERS: @@ -77,7 +77,6 @@ def core_table_sqls(): return sql_dict - class CogTable: table_config = { "name" : "base_default_table", diff --git a/meowth/core/error_handling.py b/meowth/core/error_handling.py index 63b7d4114..bb463d03e 100644 --- a/meowth/core/error_handling.py +++ b/meowth/core/error_handling.py @@ -23,8 +23,8 @@ async def delete_error(message, error): pass def missing_args(ctx): - prefix = ctx.prefix.replace(ctx.bot.user.mention, '@' + ctx.bot.user.name) - command = ctx.invoked_with + #prefix = ctx.prefix.replace(ctx.bot.user.mention, '@' + ctx.bot.user.name) + #command = ctx.invoked_with callback = ctx.command.callback sig = list(signature(callback).parameters.keys()) args, varargs, __, defaults, __, kwonlydefaults, __ = getfullargspec(callback) @@ -83,13 +83,11 @@ def check(m): elif isinstance(error, commands.CommandInvokeError): error_table = ctx.bot.dbi.table('unhandled_errors') ctx.bot.logger.exception( - "Exception in command '{}'".format(ctx.command.qualified_name), + f"Exception in command '{ctx.command.qualified_name}'", exc_info=error.original) - message = ("Error in command '{}'. This error has been logged " - "and will be tracked. Contact support for more information." - "".format(ctx.command.qualified_name)) - exception_log = ("Exception in command '{}'\n" - "".format(ctx.command.qualified_name)) + message = (f"Error in command '{ctx.command.qualified_name}'. This error has been logged " + "and will be tracked. Contact support for more information.") + exception_log = f"Exception in command '{ctx.command.qualified_name}'\n" exception_log += "".join(traceback.format_exception( type(error), error, error.__traceback__)) ctx.bot._last_exception = exception_log @@ -105,14 +103,14 @@ def check(m): insert.row(**d) await insert.commit() await ctx.send(message) - + elif isinstance(error, commands.MissingPermissions): await ctx.error("User Missing Required Permissions", - fields={"Missing": "\n".join(error.missing_perms)}) - + fields={"Missing": "\n".join(error.missing_permissions)}) + elif isinstance(error, commands.BotMissingPermissions): await ctx.error("Bot Missing Required Permissions", - fields={"Missing": "\n".join(error.missing_perms)}) + fields={"Missing": "\n".join(error.missing_permissions)}) elif isinstance(error, commands.CommandNotFound): pass @@ -121,84 +119,82 @@ def check(m): elif isinstance(error, commands.NoPrivateMessage): await ctx.send("That command is not available in DMs.") elif isinstance(error, commands.CommandOnCooldown): - await ctx.send("This command is on cooldown. " - "Try again in {:.2f}s" - "".format(error.retry_after)) - + await ctx.send(f"This command is on cooldown. Try again in {error.retry_after:.2f}s") + elif isinstance(error, errors.LocationNotSet): - msg = ('Location has not been set for this channel. Use **{prefix}setlocation** to fix.').format(prefix=prefix) + msg = f"Location has not been set for this channel. Use **{prefix}setlocation** to fix." error = await ctx.error('Location not set', details=msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.TeamSetCheckFail): - msg = _('Meowth! Team Management is not enabled on this server. **{prefix}{cmd_name}** is unable to be used.').format(cmd_name=ctx.invoked_with, prefix=prefix) + msg = f"Meowth! Team Management is not enabled on this server. **{prefix}{ctx.invoked_with}** is unable to be used." error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.WantSetCheckFail): - msg = _('Meowth! Pokemon Notifications are not enabled on this server. **{prefix}{cmd_name}** is unable to be used.').format(cmd_name=ctx.invoked_with, prefix=prefix) + msg = f"Meowth! Pokemon Notifications are not enabled on this server. **{prefix}{ctx.invoked_with}** is unable to be used." error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.WildSetCheckFail): - msg = _('Meowth! Wild Reporting is not enabled on this server. **{prefix}{cmd_name}** is unable to be used.').format(cmd_name=ctx.invoked_with, prefix=prefix) + msg = f"Meowth! Wild Reporting is not enabled on this server. **{prefix}{ctx.invoked_with}** is unable to be used." error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.ReportCheckFail): - msg = _('Meowth! Reporting is not enabled for this channel. **{prefix}{cmd_name}** is unable to be used.').format(cmd_name=ctx.invoked_with, prefix=prefix) + msg = f"Meowth! Reporting is not enabled for this channel. **{prefix}{ctx.invoked_with}** is unable to be used." error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.RaidSetCheckFail): - msg = _('Meowth! Raid Management is not enabled on this server. **{prefix}{cmd_name}** is unable to be used.').format(cmd_name=ctx.invoked_with, prefix=prefix) + msg = f"Meowth! Raid Management is not enabled on this server. **{prefix}{ctx.invoked_with}** is unable to be used." error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.EXRaidSetCheckFail): - msg = _('Meowth! EX Raid Management is not enabled on this server. **{prefix}{cmd_name}** is unable to be used.').format(cmd_name=ctx.invoked_with, prefix=prefix) + msg = f"Meowth! EX Raid Management is not enabled on this server. **{prefix}{ctx.invoked_with}** is unable to be used." error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.ResearchSetCheckFail): - msg = _('Meowth! Research Reporting is not enabled on this server. **{prefix}{cmd_name}** is unable to be used.').format(cmd_name=ctx.invoked_with, prefix=prefix) + msg = f"Meowth! Research Reporting is not enabled on this server. **{prefix}{ctx.invoked_with}** is unable to be used." error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.MeetupSetCheckFail): - msg = _('Meowth! Meetup Reporting is not enabled on this server. **{prefix}{cmd_name}** is unable to be used.').format(cmd_name=ctx.invoked_with, prefix=prefix) + msg = f"Meowth! Meetup Reporting is not enabled on this server. **{prefix}{ctx.invoked_with}** is unable to be used." error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.ArchiveSetCheckFail): - msg = _('Meowth! Channel Archiving is not enabled on this server. **{prefix}{cmd_name}** is unable to be used.').format(cmd_name=ctx.invoked_with, prefix=prefix) + msg = f"Meowth! Channel Archiving is not enabled on this server. **{prefix}{ctx.invoked_with}** is unable to be used." error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.InviteSetCheckFail): - msg = _('Meowth! EX Raid Invite is not enabled on this server. **{prefix}{cmd_name}** is unable to be used.').format(cmd_name=ctx.invoked_with, prefix=prefix) + msg = f"Meowth! EX Raid Invite is not enabled on this server. **{prefix}{ctx.invoked_with}** is unable to be used." error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.CityChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in ').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] + msg = f"'Meowth! Please use **{prefix}{ctx.invoked_with}** in " + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] if len(city_channels) > 10: - msg += _('a Region report channel.') + msg += ('a Region report channel.') else: - msg += _('one of the following region channels:') + msg += ('one of the following region channels:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: @@ -211,12 +207,12 @@ def check(m): elif isinstance(error, errors.WantChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in the following channel').format(cmd_name=ctx.invoked_with, prefix=prefix) - want_channels = bot.guild_dict[guild.id]['configure_dict']['want']['report_channels'] + msg = f"Meowth! Please use **{prefix}{ctx.invoked_with}** in the following channel" + want_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['want']['report_channels'] if len(want_channels) > 1: - msg += _('s:\n') + msg += ('s:\n') else: - msg += _(': ') + msg += (': ') counter = 0 for c in want_channels: channel = discord.utils.get(guild.channels, id=c) @@ -233,12 +229,12 @@ def check(m): elif isinstance(error, errors.RaidChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in a Raid channel. Use **{prefix}list** in any ').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] + msg = ('Meowth! Please use **{prefix}{cmd_name}** in a Raid channel. Use **{prefix}list** in any ').format(cmd_name=ctx.invoked_with, prefix=prefix) + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] if len(city_channels) > 10: - msg += _('Region report channel to see active raids.') + msg += ('Region report channel to see active raids.') else: - msg += _('of the following Region channels to see active raids:') + msg += ('of the following Region channels to see active raids:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: @@ -251,12 +247,12 @@ def check(m): elif isinstance(error, errors.EggChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in an Egg channel. Use **{prefix}list** in any ').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] + msg = ('Meowth! Please use **{prefix}{cmd_name}** in an Egg channel. Use **{prefix}list** in any ').format(cmd_name=ctx.invoked_with, prefix=prefix) + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] if len(city_channels) > 10: - msg += _('Region report channel to see active raids.') + msg += ('Region report channel to see active raids.') else: - msg += _('of the following Region channels to see active raids:') + msg += ('of the following Region channels to see active raids:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: @@ -267,25 +263,25 @@ def check(m): await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.NonRaidChannelCheckFail): - msg = _("Meowth! **{prefix}{cmd_name}** can't be used in a Raid channel.").format(cmd_name=ctx.invoked_with, prefix=prefix) + msg = f"Meowth! **{prefix}{ctx.invoked_with}** can't be used in a Raid channel." error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.ActiveRaidChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in an Active Raid channel. Use **{prefix}list** in any ').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] + msg = f"Meowth! Please use **{prefix}{ctx.invoked_with}** in an Active Raid channel. Use **{prefix}list** in any " + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] try: - egg_check = bot.guild_dict[guild.id]['raidchannel_dict'][ctx.channel.id].get('type',None) - meetup = bot.guild_dict[guild.id]['raidchannel_dict'][ctx.channel.id].get('meetup',{}) + egg_check = ctx.bot.guild_dict[guild.id]['raidchannel_dict'][ctx.channel.id].get('type',None) + meetup = ctx.bot.guild_dict[guild.id]['raidchannel_dict'][ctx.channel.id].get('meetup',{}) except: egg_check = "" meetup = False if len(city_channels) > 10: - msg += _('Region report channel to see active channels.') + msg += ('Region report channel to see active channels.') else: - msg += _('of the following Region channels to see active channels:') + msg += ('of the following Region channels to see active channels:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: @@ -293,25 +289,25 @@ def check(m): else: msg += '\n#deleted-channel' if egg_check == "egg" and not meetup: - msg += _('\nThis is an egg channel. The channel needs to be activated with **{prefix}raid ** before I accept commands!').format(prefix=prefix) + msg += f"\nThis is an egg channel. The channel needs to be activated with **{prefix}raid ** before I accept commands!" error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.ActiveChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in an Active channel. Use **{prefix}list** in any ').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] + msg = f"Meowth! Please use **{prefix}{ctx.invoked_with}** in an Active channel. Use **{prefix}list** in any " + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] try: - egg_check = bot.guild_dict[guild.id]['raidchannel_dict'][ctx.channel.id].get('type',None) - meetup = bot.guild_dict[guild.id]['raidchannel_dict'][ctx.channel.id].get('meetup',{}) + egg_check = ctx.bot.guild_dict[guild.id]['raidchannel_dict'][ctx.channel.id].get('type',None) + meetup = ctx.bot.guild_dict[guild.id]['raidchannel_dict'][ctx.channel.id].get('meetup',{}) except: egg_check = "" meetup = False if len(city_channels) > 10: - msg += _('Region report channel to see active raids.') + msg += ('Region report channel to see active raids.') else: - msg += _('of the following Region channels to see active raids:') + msg += ('of the following Region channels to see active raids:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: @@ -319,19 +315,19 @@ def check(m): else: msg += '\n#deleted-channel' if egg_check == "egg" and not meetup: - msg += _('\nThis is an egg channel. The channel needs to be activated with **{prefix}raid ** before I accept commands!').format(prefix=prefix) + msg += f"\nThis is an egg channel. The channel needs to be activated with **{prefix}raid ** before I accept commands!" error = await ctx.channel.send(msg) await asyncio.sleep(10) await delete_error(ctx.message, error) elif isinstance(error, errors.CityRaidChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in either a Raid channel or ').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] + msg = f"Meowth! Please use **{prefix}{ctx.invoked_with}** in either a Raid channel or " + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] if len(city_channels) > 10: - msg += _('a Region report channel.') + msg += ('a Region report channel.') else: - msg += _('one of the following region channels:') + msg += ('one of the following region channels:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: @@ -344,12 +340,12 @@ def check(m): elif isinstance(error, errors.RegionEggChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in either a Raid Egg channel or ').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] + msg = f"Meowth! Please use **{prefix}{ctx.invoked_with}** in either a Raid Egg channel or " + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['raid']['report_channels'] if len(city_channels) > 10: - msg += _('a Region report channel.') + msg += ('a Region report channel.') else: - msg += _('one of the following region channels:') + msg += ('one of the following region channels:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: @@ -362,12 +358,12 @@ def check(m): elif isinstance(error, errors.RegionExRaidChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in either a EX Raid channel or one of the following region channels:').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['exraid']['report_channels'] + msg = f"Meowth! Please use **{prefix}{ctx.invoked_with}** in either a EX Raid channel or one of the following region channels:" + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['exraid']['report_channels'] if len(city_channels) > 10: - msg += _('a Region report channel.') + msg += ('a Region report channel.') else: - msg += _('one of the following region channels:') + msg += ('one of the following region channels:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: @@ -380,12 +376,12 @@ def check(m): elif isinstance(error, errors.ExRaidChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in a EX Raid channel. Use **{prefix}list** in any of the following region channels to see active raids:').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['exraid']['report_channels'] + msg = f"Meowth! Please use **{prefix}{ctx.invoked_with}** in a EX Raid channel. Use **{prefix}list** in any of the following region channels to see active raids:" + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['exraid']['report_channels'] if len(city_channels) > 10: - msg += _('a Region report channel.') + msg += ('a Region report channel.') else: - msg += _('one of the following region channels:') + msg += ('one of the following region channels:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: @@ -398,12 +394,12 @@ def check(m): elif isinstance(error, errors.ResearchReportChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in ').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['research']['report_channels'] + msg = f"Meowth! Please use **{prefix}{ctx.invoked_with}** in " + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['research']['report_channels'] if len(city_channels) > 10: - msg += _('a Region report channel.') + msg += ('a Region report channel.') else: - msg += _('one of the following region channels:') + msg += ('one of the following region channels:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: @@ -416,12 +412,12 @@ def check(m): elif isinstance(error, errors.MeetupReportChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in ').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['meetup']['report_channels'] + msg = f"Meowth! Please use **{prefix}{ctx.invoked_with}** in " + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['meetup']['report_channels'] if len(city_channels) > 10: - msg += _('a Region report channel.') + msg += ('a Region report channel.') else: - msg += _('one of the following region channels:') + msg += ('one of the following region channels:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: @@ -434,12 +430,12 @@ def check(m): elif isinstance(error, errors.WildReportChannelCheckFail): guild = ctx.guild - msg = _('Meowth! Please use **{prefix}{cmd_name}** in ').format(cmd_name=ctx.invoked_with, prefix=prefix) - city_channels = bot.guild_dict[guild.id]['configure_dict']['wild']['report_channels'] + msg = f"Meowth! Please use **{prefix}{ctx.invoked_with}** in " + city_channels = ctx.bot.guild_dict[guild.id]['configure_dict']['wild']['report_channels'] if len(city_channels) > 10: - msg += _('a Region report channel.') + msg += ('a Region report channel.') else: - msg += _('one of the following region channels:') + msg += ('one of the following region channels:') for c in city_channels: channel = discord.utils.get(guild.channels, id=c) if channel: diff --git a/meowth/core/errors.py b/meowth/core/errors.py index 1fd86292b..0983bafa3 100644 --- a/meowth/core/errors.py +++ b/meowth/core/errors.py @@ -1,113 +1,86 @@ from discord.ext.commands import CommandError -from meowth.core.data_manager.errors import * +import meowth.core.data_manager.errors class LocationNotSet(CommandError): 'Exception raised checks.location_set fails' - pass class MissingSubcommand(CommandError): pass class TeamSetCheckFail(CommandError): 'Exception raised checks.teamset fails' - pass class WantSetCheckFail(CommandError): 'Exception raised checks.wantset fails' - pass class WildSetCheckFail(CommandError): 'Exception raised checks.wildset fails' - pass class ReportCheckFail(CommandError): 'Exception raised checks.allowreport fails' - pass class RaidSetCheckFail(CommandError): 'Exception raised checks.raidset fails' - pass class EXRaidSetCheckFail(CommandError): 'Exception raised checks.exraidset fails' - pass class ResearchSetCheckFail(CommandError): 'Exception raised checks.researchset fails' - pass class MeetupSetCheckFail(CommandError): 'Exception raised checks.meetupset fails' - pass class ArchiveSetCheckFail(CommandError): 'Exception raised checks.archiveset fails' - pass class InviteSetCheckFail(CommandError): 'Exception raised checks.inviteset fails' - pass class CityChannelCheckFail(CommandError): 'Exception raised checks.citychannel fails' - pass class WantChannelCheckFail(CommandError): 'Exception raised checks.wantchannel fails' - pass class RaidChannelCheckFail(CommandError): 'Exception raised checks.raidchannel fails' - pass class EggChannelCheckFail(CommandError): 'Exception raised checks.eggchannel fails' - pass class NonRaidChannelCheckFail(CommandError): 'Exception raised checks.nonraidchannel fails' - pass class ActiveRaidChannelCheckFail(CommandError): 'Exception raised checks.activeraidchannel fails' - pass class ActiveChannelCheckFail(CommandError): 'Exception raised checks.activechannel fails' - pass class CityRaidChannelCheckFail(CommandError): 'Exception raised checks.cityraidchannel fails' - pass class RegionEggChannelCheckFail(CommandError): 'Exception raised checks.cityeggchannel fails' - pass class RegionExRaidChannelCheckFail(CommandError): 'Exception raised checks.allowexraidreport fails' - pass class ExRaidChannelCheckFail(CommandError): 'Exception raised checks.cityeggchannel fails' - pass class ResearchReportChannelCheckFail(CommandError): 'Exception raised checks.researchreport fails' - pass class MeetupReportChannelCheckFail(CommandError): 'Exception raised checks.researchreport fails' - pass class WildReportChannelCheckFail(CommandError): 'Exception raised checks.researchreport fails' - pass class TradeChannelCheckFail(CommandError): 'Exception raised checks.tradereport fails' - pass class TradeSetCheckFail(CommandError): 'Exception raised checks.tradeset fails' - pass diff --git a/meowth/exts/admin/admin_cog.py b/meowth/exts/admin/admin_cog.py index 8ed4330e4..9d0e6a4ff 100644 --- a/meowth/exts/admin/admin_cog.py +++ b/meowth/exts/admin/admin_cog.py @@ -55,7 +55,7 @@ def template_replace(match): return (msg, not_found) class AdminCog(Cog): - + def __init__(self, bot): self.bot = bot @@ -94,7 +94,7 @@ async def on_guild_channel_update(self, before, after): return except: pass - + @Cog.listener() async def on_member_join(self, member): guild = member.guild @@ -142,7 +142,7 @@ def check_channel_perms(self, channel, required_perms): missing_perms.append(x[0]) missing_perms = [x.replace('_', ' ').replace('guild', 'server').title() for x in missing_perms] return missing_perms - + async def welcome_channel(self, guild): table = self.bot.dbi.table('welcome') query = table.query @@ -160,7 +160,7 @@ async def welcome_channel(self, guild): return 'dm', message else: return None, None - + async def archive_cat_phrases(self, guild): table = self.bot.dbi.table('archive') query = table.query @@ -174,7 +174,7 @@ async def archive_cat_phrases(self, guild): cat = self.bot.get_channel(catid) phrase_list = data.get('phrase_list', []) return cat, phrase_list - + @command() @commands.has_permissions(manage_guild=True) async def teamrole(self, ctx, team: Team, role: discord.Role): @@ -236,7 +236,7 @@ async def addcustomroles(self, ctx, roles: commands.Greedy[discord.Role]): insert.rows(rows) await insert.commit(do_update=True) await ctx.success('Custom roles added', details="\n".join(role_names)) - + @command() @checks.is_admin() async def removecustomroles(self, ctx, roles: commands.Greedy[discord.Role]): @@ -361,56 +361,112 @@ def check(m): await ctx.send('I could not interpret your response. Try again!') continue if 'raid' in enabled_commands: - raid_levels = ['1', '3', '5', '7', 'EX', 'EX Raid Gyms'] - for level in raid_levels: - column = f'category_{level.lower()}' - if level == 'EX Raid Gyms': - column = 'category_ex_gyms' - content = ('I can categorize raids of any level that are reported at ' - 'recognized EX Raid Gyms differently from other raids of the same level. ' - 'You can type `disable` if you do not want this, or type the name or ID of ' - 'the category you want those raid channels to appear in.') - else: - if level == '7': - level_str = 'Mega' - elif level == 'EX': - level_str = "EX" - else: - level_str = f"Level {level}" - content = (f'How do you want {level_str} Raids reported in this ' - 'channel to be displayed? You can type `message` if you want just ' - 'a message in this channel. If you want each raid to be given its own ' - 'channel for coordination, type the name or ID of the category you ' - 'want the channel to appear in, or type `none` for an uncategorized ' - 'channel. You can also type `disable` to disallow reports of ' - f'{level_str} Raids in this channel.') - await ctx.send(content) - def check(m): - return m.author == ctx.message.author and m.channel == ctx.channel - while True: - try: - resp = await self.bot.wait_for('message', check=check) - except: - break - if resp.content.lower() == 'message': - rcrd[column] = 'message' - break - elif resp.content.lower() == 'disable': - rcrd[column] = None - break - elif resp.content.lower() == 'none': - rcrd[column] = 'none' - break - else: - converter = commands.CategoryChannelConverter() - category = await converter.convert(ctx, resp.content) - if category: - rcrd[column] = str(category.id) - required_perms['Manage Channels'] = perms.manage_channels + raid_levels = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', 'EX', 'EX Raid Gyms'] + + await ctx.send('I can use channel categories for to help you organise raids. There are currently 15 raid levels. Would you like to use a single category or multiple categories to organise them?' + 'Choose either of `single` or `multiple`.') + def check(m): + return m.author == ctx.message.author and m.channel == ctx.channel + while True: + try: + resp = await self.bot.wait_for('message', check=check) + except: + break + if resp.content.lower() == 'single': + await ctx.send(f'How do you want raids reported in this ' + 'channel to be displayed? You can type `message` if you want just ' + 'a message in this channel. If you want each raid to be given its own ' + 'channel for coordination, type the name or ID of the category you ' + 'want the channel to appear in, or type `none` for an uncategorized ' + 'channel.') + while True: + try: + resp = await self.bot.wait_for('message', check=check) + except: + break + if resp.content.lower() == 'message': + for level in raid_levels: + column = f'category_{level.lower()}' + if level == 'EX Raid Gyms': + column = 'category_ex_gyms' + rcrd[column] = 'message' + break + elif resp.content.lower() == 'none': + for level in raid_levels: + column = f'category_{level.lower()}' + if level == 'EX Raid Gyms': + column = 'category_ex_gyms' + rcrd[column] = 'none' break else: - await ctx.send('I could not interpret your response. Try again!') - continue + converter = commands.CategoryChannelConverter() + category = await converter.convert(ctx, resp.content) + if category: + for level in raid_levels: + column = f'category_{level.lower()}' + if level == 'EX Raid Gyms': + column = 'category_ex_gyms' + rcrd[column] = str(category.id) + required_perms['Manage Channels'] = perms.manage_channels + break + else: + await ctx.send('I could not interpret your response. Try again!') + continue + break + elif resp.content.lower() == 'multiple': + for level in raid_levels: + column = f'category_{level.lower()}' + if level == 'EX Raid Gyms': + column = 'category_ex_gyms' + content = ('I can categorize raids of any level that are reported at ' + 'recognized EX Raid Gyms differently from other raids of the same level. ' + 'You can type `disable` if you do not want this, or type the name or ID of ' + 'the category you want those raid channels to appear in.') + else: + if level == '6': + level_str = 'Mega (Normal)' + elif level == '7': + level_str = 'Mega (Legendary)' + elif level == 'EX': + level_str = "EX" + else: + level_str = f"Level {level}" + content = (f'How do you want {level_str} Raids reported in this ' + 'channel to be displayed? You can type `message` if you want just ' + 'a message in this channel. If you want each raid to be given its own ' + 'channel for coordination, type the name or ID of the category you ' + 'want the channel to appear in, or type `none` for an uncategorized ' + 'channel. You can also type `disable` to disallow reports of ' + f'{level_str} Raids in this channel.') + await ctx.send(content) + while True: + try: + resp = await self.bot.wait_for('message', check=check) + except: + break + if resp.content.lower() == 'message': + rcrd[column] = 'message' + break + elif resp.content.lower() == 'disable': + rcrd[column] = None + break + elif resp.content.lower() == 'none': + rcrd[column] = 'none' + break + else: + converter = commands.CategoryChannelConverter() + category = await converter.convert(ctx, resp.content) + if category: + rcrd[column] = str(category.id) + required_perms['Manage Channels'] = perms.manage_channels + break + else: + await ctx.send('I could not interpret your response. Try again!') + continue + break + else: + await ctx.send("I couldn't understand your reply. Try again.") + continue if 'welcome' in enabled_commands: old_welcome_channel, message = await self.welcome_channel(ctx.guild) new_welcome_channel = None @@ -771,17 +827,47 @@ async def importconfig(self, ctx): d['category_3'] = cat d['category_4'] = cat d['category_5'] = cat + d['category_6'] = cat + d['category_7'] = cat + d['category_8'] = cat + d['category_9'] = cat + d['category_10'] = cat + d['category_11'] = cat + d['category_12'] = cat + d['category_13'] = cat + d['category_14'] = cat + d['category_15'] = cat elif catsort == 'level': cat_1 = str(cat_dict.get('1')) cat_2 = str(cat_dict.get('2')) cat_3 = str(cat_dict.get('3')) cat_4 = str(cat_dict.get('4')) cat_5 = str(cat_dict.get('5')) + cat_5 = str(cat_dict.get('6')) + cat_5 = str(cat_dict.get('7')) + cat_5 = str(cat_dict.get('8')) + cat_5 = str(cat_dict.get('9')) + cat_5 = str(cat_dict.get('10')) + cat_5 = str(cat_dict.get('11')) + cat_5 = str(cat_dict.get('12')) + cat_5 = str(cat_dict.get('13')) + cat_5 = str(cat_dict.get('14')) + cat_5 = str(cat_dict.get('15')) d['category_1'] = cat_1 d['category_2'] = cat_2 d['category_3'] = cat_3 d['category_4'] = cat_4 d['category_5'] = cat_5 + d['category_6'] = cat + d['category_7'] = cat + d['category_8'] = cat + d['category_9'] = cat + d['category_10'] = cat + d['category_11'] = cat + d['category_12'] = cat + d['category_13'] = cat + d['category_14'] = cat + d['category_15'] = cat elif catsort == 'same': cat = str(channel_exists.category.id) d['category_1'] = cat @@ -789,12 +875,32 @@ async def importconfig(self, ctx): d['category_3'] = cat d['category_4'] = cat d['category_5'] = cat + d['category_6'] = cat + d['category_7'] = cat + d['category_8'] = cat + d['category_9'] = cat + d['category_10'] = cat + d['category_11'] = cat + d['category_12'] = cat + d['category_13'] = cat + d['category_14'] = cat + d['category_15'] = cat else: d['category_1'] = 'none' d['category_2'] = 'none' d['category_3'] = 'none' d['category_4'] = 'none' d['category_5'] = 'none' + d['category_6'] = 'none' + d['category_7'] = 'none' + d['category_8'] = 'none' + d['category_9'] = 'none' + d['category_10'] = 'none' + d['category_11'] = 'none' + d['category_12'] = 'none' + d['category_13'] = 'none' + d['category_14'] = 'none' + d['category_15'] = 'none' report_channels[chan] = d exraid_dict = old_config.get('exraid', {}) if exraid_dict.get('enabled'): @@ -940,7 +1046,7 @@ async def cleanroles(self, ctx): except: pass await ctx.send(f'Deleted {deleted_roles} empty roles') - + @command() @checks.is_admin() async def configure(self, ctx): @@ -965,4 +1071,4 @@ async def configure(self, ctx): f'Meowth 2.0 configuration, please use `{ctx.prefix}importconfig` to attempt to ' 'import your settings before attempting to configure Meowth 3.0. If this is not done, ' 'you may find that both Meowth versions attempt to respond to your commands.') - + diff --git a/meowth/exts/map/map_cog.py b/meowth/exts/map/map_cog.py index b540f8218..92ff9ded9 100644 --- a/meowth/exts/map/map_cog.py +++ b/meowth/exts/map/map_cog.py @@ -22,10 +22,9 @@ from typing import List import tempfile -from .map_info import gmaps_api_key from .errors import * -gmaps = googlemaps.Client(key=gmaps_api_key) +gmaps = googlemaps.Client(key=bot.config.gmapsapikey) class ReportChannel(): @@ -209,7 +208,15 @@ async def get_raid_lists(self): "5": {}, "6": {}, "EX": {}, - "7": {} + "7": {}, + "8": {}, + "9": {}, + "10": {}, + "11": {}, + "12": {}, + "13": {}, + "14": {}, + "15": {} } table = self.bot.dbi.table('raid_bosses') query = table.query @@ -239,7 +246,8 @@ def data(rcrd): regiondata = await query.get() if not regiondata: continue - raid_lists[level][boss_id] = d + if d.get("available"): + raid_lists[level][boss_id] = d return raid_lists async def get_map(self): @@ -1018,7 +1026,7 @@ async def whereis(self, ctx, *, location: POI): content = f"{display_str}\n[Directions]({url})" if isinstance(location, Gym): thumbnail = ("https://raw.githubusercontent.com/" - "FoglyOgly/Meowth/new-core/meowth/images/misc/gym.png") + "jackyaz/Meowth/self-host/meowth/images/misc/gym.png") if await location._exraid(): title = "EX Raid Gym" else: @@ -1026,7 +1034,7 @@ async def whereis(self, ctx, *, location: POI): elif isinstance(location, Pokestop): title = "Pokestop" thumbnail = ("https://raw.githubusercontent.com/" - "FoglyOgly/Meowth/new-core/meowth/images/misc/pokestop.png") + "jackyaz/Meowth/self-host/meowth/images/misc/pokestop.png") color = ctx.guild.me.color embed = formatters.make_embed(title=title, content=content, thumbnail=thumbnail, msg_colour=color) await ctx.send(embed=embed) diff --git a/meowth/exts/map/map_info.py b/meowth/exts/map/map_info.py deleted file mode 100644 index 94386568e..000000000 --- a/meowth/exts/map/map_info.py +++ /dev/null @@ -1 +0,0 @@ -gmaps_api_key = 'apikeygoeshere' \ No newline at end of file diff --git a/meowth/exts/pkmn/pkmn_cog.py b/meowth/exts/pkmn/pkmn_cog.py index 4599a047f..38e93fdb5 100644 --- a/meowth/exts/pkmn/pkmn_cog.py +++ b/meowth/exts/pkmn/pkmn_cog.py @@ -86,10 +86,10 @@ def to_dict(self): 'chargeMove2id': self.chargeMove2id } return d - + def __repr__(self): return repr(self.to_dict) - + @classmethod def from_dict(cls, bot, data): pkmn_id = data['id'] @@ -106,9 +106,9 @@ def from_dict(cls, bot, data): chargeMove2id = data['chargeMove2id'] return cls(bot, pkmn_id, form=form, gender=gender, shiny=shiny, attiv=attiv, defiv=defiv, staiv=staiv, - lvl=lvl, cp=cp, quickMoveid=quickMoveid, + lvl=lvl, cp=cp, quickMoveid=quickMoveid, chargeMoveid=chargeMoveid, chargeMove2id=chargeMove2id) - + async def moveset_str(self): fast = self.quickMoveid or None charge = self.chargeMoveid or None @@ -140,7 +140,7 @@ async def moveset_str(self): charge2_emoji = await charge2_move.emoji() moveset_str += f'| {charge2_name} {charge2_emoji}' return moveset_str - + async def trade_display_str(self): name = await self.name() if self.shiny: @@ -164,29 +164,29 @@ async def trade_display_str(self): level_str = "" display_str = f"{shiny_str}{gender_str}{level_str}{name}{moveset_str}" return display_str - + @property def _data(self): pokemon_ref = self.bot.dbi.table('pokemon').query() data = pokemon_ref.where(pokemonid=self.id) return data - - + + async def _num(self): data = self._data return await data.select('num').get_value() - + async def _gen(self): data = self._data return await data.select('gen').get_value() - - + + async def _type(self): data = self._data return await data.select('type').get_value() - - + + async def _type2(self): data = self._data return await data.select('type2').get_value() @@ -194,15 +194,18 @@ async def _type2(self): async def boost_weather(self): type1 = await self._type() type2 = await self._type2() - types_table = self.bot.dbi.table('types') - weather_query = types_table.query('weather') + weather = [] + + if type1 is None: + return weather + if not type2: - weather_query.where(typeid=type1) + weather.append(self.bot.config.type_emoji.get(type1.replace("POKEMON_TYPE_","").lower()).get("weather")) else: - weather_query.where((types_table['typeid']==type1, types_table['typeid']==type2)) - weather = await weather_query.get_values() + weather.append(self.bot.config.type_emoji.get(type1.replace("POKEMON_TYPE_","").lower()).get("weather")) + weather.append(self.bot.config.type_emoji.get(type2.replace("POKEMON_TYPE_","").lower()).get("weather")) return weather - + async def weather_str(self): weather = await self.boost_weather() weather_names = [] @@ -215,47 +218,46 @@ async def weather_str(self): async def is_boosted(self, weather): boost_weather = await self.boost_weather() return weather in boost_weather - - + + async def type_emoji(self): emoji_string = '' type1 = await self._type() - type1_ref = self.bot.dbi.table('types').query().select('emoji').where(typeid=type1) - type1_emoji = await type1_ref.get_value() + type1_emoji = self.bot.config.type_emoji.get(type1.replace("POKEMON_TYPE_","").lower()).get("emoji") + type2 = await self._type2() type2_emoji = '' if type2: - type2_ref = self.bot.dbi.table('types').query().select('emoji').where(typeid=type2) - type2_emoji = await type2_ref.get_value() + type2_emoji = self.bot.config.type_emoji.get(type2.replace("POKEMON_TYPE_","").lower()).get("emoji") emoji_string += type1_emoji emoji_string += type2_emoji return emoji_string - - + + async def _form_type_id(self): data = self._data return await data.select('form_type_id').get_value() - - + + async def _gender_type(self): data = self._data return await data.select('gender_type').get_value() - - + + async def _mythical(self): data = self._data return await data.select('mythical').get_value() - - + + async def _legendary(self): data = self._data return await data.select('legendary').get_value() - - + + async def _wild_available(self): data = self._data return await data.select('wild_available').get_value() - + async def _raid_available(self, coords): table = self.bot.dbi.table('raid_bosses') query = table.query @@ -288,7 +290,7 @@ async def _research_available(self): query = research_table.query('reward') rewards = await query.get_values() return self.id in rewards - + async def _shiny_available(self): data = self._data return await data.select('shiny_available').get_value() @@ -296,75 +298,75 @@ async def _shiny_available(self): async def _mega_available(self): data = self._data return await data.select('mega_available').get_value() - + async def _baseStamina(self): data = self._data return await data.select('baseStamina').get_value() - - + + async def _baseAttack(self): data = self._data return await data.select('baseAttack').get_value() - - + + async def _baseDefense(self): data = self._data return await data.select('baseDefense').get_value() - - + + async def _HeightM(self): data = self._data return await data.select('HeightM').get_value() - - + + async def _WeightKg(self): data = self._data return await data.select('WeightKg').get_value() - - + + async def _HeightStdDev(self): data = self._data return await data.select('HeightStdDev').get_value() - - + + async def _WeightStdDev(self): data = self._data return await data.select('WeightStdDev').get_value() - - + + async def _familyId(self): data = self._data return await data.select('familyId').get_value() - - + + async def _stageID(self): data = self._data return await data.select('stageID').get_value() - - + + async def _evolves_from(self): data = self._data return await data.select('evolves_from').get_value() - - + + async def _evo_cost_candy(self): data = self._data return await data.select('evo_cost_candy').get_value() - - + + async def _evo_cost_item(self): data = self._data return await data.select('evo_cost_item').get_value() - - + + async def _evo_condition(self): data = self._data return await data.select('evo_condition').get_value() - - + + async def sprite_url(self): url = ("https://raw.githubusercontent.com/" - "FoglyOgly/Meowth/new-core/meowth/images/pkmn/") + "jackyaz/Meowth/self-host/meowth/images/pkmn/") url += self.id if self.form: url += '_' @@ -377,28 +379,32 @@ async def sprite_url(self): url += self.gender.upper() url += '.png?cache=5' return url - + + async def color(self): url = await self.sprite_url() color = await formatters.url_color(url) return color + @property def _dex_data(self): dex_ref = self.bot.dbi.table('pokedex').query().where(pokemonid=self.id) data = dex_ref.where(language_id=9) return data - + async def name(self): dex_data = self._dex_data name = await dex_data.select('name').get_value() + if name is None: + return f"MISSINGNO - {self.id} - DO NOT USE - REPORT TO ADMIN" name = name.strip() if self.form == 64: - pure_emoji = self.bot.get_emoji(603609730232877088) + pure_emoji = self.bot.config.form_emoji['purified'] name += f" {str(pure_emoji)}" elif self.form == 63: - shadow_emoji = self.bot.get_emoji(603609764882022440) + shadow_emoji = self.bot.config.form_emoji['shadow'] name += f" {str(shadow_emoji)}" elif self.form: name += " " @@ -408,18 +414,18 @@ async def name(self): form_name = await form_name_query.get_value() name += form_name return name - - + + async def description(self): dex_data = self._dex_data return await dex_data.select('description').get_value() - - + + async def category(self): dex_data = self._dex_data return await dex_data.select('category').get_value() - - + + async def type_dict(self): type_chart_ref = self.bot.dbi.table('type_chart').query() type1_ref = await type_chart_ref.where(defender_type_id=await self._type()).get() @@ -441,16 +447,16 @@ async def type_dict(self): for type in type1_dict: type_dict[type] = type1_dict[type] * type2_dict.get(type, 1) return type_dict - - + + async def type_chart(self): type_dict = await self.type_dict() type_chart = {} for type in type_dict: type_chart[type] = round(log(float(type_dict[type]), 1.6)) return type_chart - - + + async def weaknesses_emoji(self): type_chart = await self.type_chart() types_sorted = sorted(type_chart.items(), key=(lambda x: x[1]), reverse=True) @@ -459,8 +465,7 @@ async def weaknesses_emoji(self): for type_tuple in types_sorted: if i == 4: emoji_string += '\n' - type_ref = self.bot.dbi.table('types').query() - emoji = await type_ref.select('emoji').where(typeid=type_tuple[0]).get_value() + emoji = self.bot.config.type_emoji.get(type_tuple[0].replace("POKEMON_TYPE_","").lower()).get("emoji") if type_tuple[1] == 4: emoji += 'x4' emoji_string += emoji @@ -477,7 +482,7 @@ async def weaknesses_emoji(self): i += 1 return emoji_string - + async def resistances_emoji(self): type_chart = await self.type_chart() types_sorted = sorted(type_chart.items(), key=(lambda x: x[1])) @@ -486,8 +491,8 @@ async def resistances_emoji(self): for type_tuple in types_sorted: if i == 4: emoji_string += '\n' - type_ref = self.bot.dbi.table('types').query() - emoji = await type_ref.select('emoji').where(typeid=type_tuple[0]).get_value() + emoji = self.bot.config.type_emoji.get(type_tuple[0].replace("POKEMON_TYPE_","").lower()).get("emoji") + if type_tuple[1] == -4: emoji += 'x4' emoji_string += emoji @@ -503,8 +508,8 @@ async def resistances_emoji(self): break i += 1 return emoji_string - - + + async def moves(self): movesets_query = await self.bot.dbi.table('movesets').query().where( pokemonid=self.id).get() @@ -517,7 +522,7 @@ async def legacy_moves(self): moves = await self.bot.dbi.table('movesets').query('moveid').where( pokemonid=self.id).where(legacy=True).get_values() return moves - + async def fast_moves(self): moves = await self.moves() fast_moves = [] @@ -527,7 +532,7 @@ async def fast_moves(self): fast_moves.append(move.id) return fast_moves - + async def charge_moves(self): moves = await self.moves() charge_moves = [] @@ -536,8 +541,8 @@ async def charge_moves(self): if not await move._fast(): charge_moves.append(move.id) return charge_moves - - + + async def dex_embed(self): num = await self._num() description = await self.description() @@ -599,7 +604,7 @@ async def dex_embed(self): footer = '* denotes legacy move' ) return embed - + @staticmethod async def get_all_forms(bot, pokemonid): table = bot.dbi.table('pokemon') @@ -617,8 +622,8 @@ async def get_megas(self): query.where(evolves_from=self.id) ids = await query.get_values() return ids - - + + async def cpm(self): if not self.lvl: return None @@ -627,8 +632,8 @@ async def cpm(self): level=self.lvl) cpm = await cpm_ref.select('cpm').get_value() return cpm - - + + async def calculate_cp(self): if None in [self.lvl, self.attiv, self.defiv, self.staiv]: return None @@ -653,7 +658,7 @@ async def min_cp(self, level=1): if cp < 10: cp = 10 return cp - + async def max_cp(self, level=40): cpm_ref = self.bot.dbi.table('cpm_table').query('cpm').where( level=level) @@ -665,7 +670,7 @@ async def max_cp(self, level=40): if cp < 10: cp = 10 return cp - + async def validate(self, context, weather=None): if self.quickMoveid: quick_moves = await self.fast_moves() @@ -731,7 +736,7 @@ async def validate(self, context, weather=None): elif self.chargeMove2id in legacy_moves: raise MoveInvalidLegacy(self, self.chargeMove2id) return self - + async def get_info_from_arg(self, bot, arg): if arg.startswith('cp'): if len(arg) == 2: @@ -938,7 +943,7 @@ async def from_arg(cls, bot, command_name, chn, user_id, arg, coords=None): pkmn.gender = gender return pkmn - @classmethod + @classmethod async def convert(cls, ctx, arg): report_channel = ReportChannel(ctx.bot, ctx.channel) coords = await report_channel.center_coords() @@ -960,74 +965,74 @@ def __init__( def _data(self): data = self.bot.dbi.table('moves').query().where(moveid=self.id) return data - - + + async def _fast(self): data = self._data is_fast = await data.select('fast').get_value() return is_fast - + async def is_legacy(self, pkmn_id): movesets_table = self.bot.dbi.table('movesets') query = movesets_table.query('legacy') query.where(pokemonid=pkmn_id) query.where(moveid=self.id) - return await query.get_value() - + return await query.get_value() + async def _type(self): data = self._data move_type = await data.select('type').get_value() return move_type - - + + async def _power(self): data = self._data power = await data.select('power').get_value() return power - - + + async def _criticalChance(self): data = self._data critChance = await data.select('criticalChance').get_value() return critChance - - + + async def _staminaLossScalar(self): data = self._data stamloss = await data.select('staminaLossScalar').get_value() return stamloss - - + + async def _durationMs(self): data = self._data duration = await data.select('durationMs').get_value() return duration - - + + async def _damageWindowStartMs(self): data = self._data start = await data.select('damageWindowStartMs').get_value() return start - - + + async def _damageWindowEndMs(self): data = self._data end = await data.select('damageWindowEndMs').get_value() return end - - + + async def _energyDelta(self): data = self._data energy = await data.select('energyDelta').get_value() return energy - - + + async def dps(self): power = await self._power() duration = await self._durationMs() return (power*1000/duration) - - + + async def eps(self): if not await self._fast(): return None @@ -1035,8 +1040,8 @@ async def eps(self): energy = await self._energyDelta() duration = await self._durationMs() return (energy*1000/duration) - - + + async def dpe(self): if await self._fast(): return None @@ -1044,21 +1049,20 @@ async def dpe(self): energy = await self._energyDelta() power = await self._power() return (power/energy) - - + + async def emoji(self): _type = await self._type() - type_ref = self.bot.dbi.table('types').query().where(typeid=_type) - emoji = await type_ref.select('emoji').get_value() + emoji = self.bot.config.type_emoji.get(_type.replace("POKEMON_TYPE_","").lower()).get("emoji") return emoji - - + + async def name(self): names_ref = self.bot.dbi.table('move_names').query().where(moveid=self.id).where( language_id=9) name = await names_ref.select('name').get_value() return name - + @classmethod async def from_arg(cls, bot, arg): names = bot.dbi.table('move_names') @@ -1069,18 +1073,18 @@ async def from_arg(cls, bot, arg): return cls(bot, match_id) else: raise MoveNotFound - + @classmethod async def convert(cls, ctx, arg): return await cls.from_arg(ctx.bot, arg) - - + + class Pokedex(Cog): def __init__(self, bot): self.bot = bot - + @Cog.listener() async def on_command_error(self, ctx, error): if isinstance(error, PokemonNotFound): @@ -1124,17 +1128,18 @@ async def get_wilds(self, current): current_ids = await dex_query.get_values() ids = list(set(current_ids).intersection(set(wild_ids))) return [Pokemon(self.bot, x) for x in ids] - + @command() async def pokedex(self, ctx, *, pokemon: Pokemon): """Display a Pokedex entry.""" embed = await pokemon.dex_embed() embed.color = ctx.guild.me.color return await ctx.send(embed=embed) - + @command() @checks.is_co_owner() async def movesupdate(self, ctx): + await ctx.send('Updating movesets table') async with aiohttp.ClientSession() as sess: async with sess.get('https://fight.pokebattler.com/pokemon') as resp: data = await resp.json() @@ -1165,5 +1170,52 @@ async def movesupdate(self, ctx): insert.rows(move_list) await movesets_table.query().delete() await insert.commit() - return await ctx.send('Movesets table updated') - + await ctx.send('Movesets table updated') + + await ctx.send('Updating moves table') + async with aiohttp.ClientSession() as sess: + async with sess.get('https://fight.pokebattler.com/moves') as resp: + data = await resp.json() + + movenames_dicts = data['move'] + movename_list = [] + moves_list = [] + + for movename in movenames_dicts: + if movename.get('moveId'): + movename_list.append({ + 'moveid': movename.get('moveId'), + 'language_id': 9, + 'name': movename.get('moveId').replace('_FAST','').replace('_',' ').title() + }) + if movename.get('type'): + fast = False + if movename.get('moveId').endswith("_FAST"): + fast = True + moves_list.append({ + 'moveid': movename.get('moveId'), + 'fast': fast, + 'type': movename.get('type'), + 'power': movename.get('power'), + 'criticalchance': movename.get('criticalChance'), + 'staminalossscalar': movename.get('staminaLossScalar'), + 'durationms': movename.get('durationMs'), + 'damagewindowstartms': movename.get('damageWindowStartMs', 0), + 'damagewindowendms': movename.get('damageWindowEndMs', 0), + 'energydelta': movename.get('energyDelta') + }) + + movenames_table = ctx.bot.dbi.table('move_names') + insert = movenames_table.insert() + insert.rows(movename_list) + await movenames_table.query().delete() + await insert.commit() + + moves_table = ctx.bot.dbi.table('moves') + insert = moves_table.insert() + insert.rows(moves_list) + await moves_table.query().delete() + await insert.commit() + + return await ctx.send('Moves table updated') + diff --git a/meowth/exts/raid/__init__.py b/meowth/exts/raid/__init__.py index e4649a43c..598583b3e 100644 --- a/meowth/exts/raid/__init__.py +++ b/meowth/exts/raid/__init__.py @@ -14,4 +14,4 @@ def setup(bot): pass tree.add_command(raid_command_group) bot.loop.create_task(tree.sync()) - bot.tree = tree \ No newline at end of file + bot.tree = tree diff --git a/meowth/exts/raid/errors.py b/meowth/exts/raid/errors.py index 724dc18bc..d97827642 100644 --- a/meowth/exts/raid/errors.py +++ b/meowth/exts/raid/errors.py @@ -31,6 +31,3 @@ class RaidNotActive(CommandError): class MeetupDisabled(CommandError): 'Exception raised, meetup not enabled' pass - - - diff --git a/meowth/exts/raid/objects.py b/meowth/exts/raid/objects.py index c4e2010e5..2bddd05d9 100644 --- a/meowth/exts/raid/objects.py +++ b/meowth/exts/raid/objects.py @@ -1,3 +1,13 @@ +import asyncio +from datetime import datetime +from math import ceil +import time +import re +import aiohttp +import discord +from discord.ext import commands +from pytz import timezone + from meowth.exts.map import Gym, ReportChannel, Mapper, PartialPOI, POI from meowth.exts.users import MeowthUser from meowth.exts.pkmn import Pokemon, Move @@ -9,21 +19,16 @@ from .raid_checks import archive_category from . import raid_info -import asyncio -import aiohttp -from datetime import datetime -from math import ceil -import discord -from discord.ext import commands -import time -from pytz import timezone - emoji_letters = ['🇦','🇧','🇨','🇩','🇪','🇫','🇬','🇭','🇮','🇯','🇰','🇱', '🇲','🇳','🇴','🇵','🇶','🇷','🇸','🇹','🇺','🇻','🇼','🇽','🇾','🇿' ] -class RaidBoss(Pokemon): +seconds_per_unit = {"s": 1, "m": 60, "h": 3600, "d": 86400, "w": 604800} + +def convert_to_seconds(s): + return int(s[:-1]) * seconds_per_unit[s[-1]] +class RaidBoss(Pokemon): def __init__(self, pkmn): self.bot = pkmn.bot self.id = pkmn.id @@ -54,15 +59,13 @@ async def _shiny_available(self): elif await super()._evolves_from(): return False return True - + @classmethod async def convert(cls, ctx, arg): pkmn = await Pokemon.convert(ctx, arg) - return cls(pkmn) - + return cls(pkmn) class Meetup: - instances = dict() by_message = dict() by_channel = dict() @@ -73,7 +76,7 @@ def __new__(cls, meetup_id, *args, **kwargs): instance = super().__new__(cls) cls.instances[meetup_id] = instance return instance - + def __init__(self, meetup_id, bot, guild_id, channel_id, report_channel_id, location, start, tz): self.id = meetup_id self.bot = bot @@ -87,7 +90,7 @@ def __init__(self, meetup_id, bot, guild_id, channel_id, report_channel_id, loca self.message_ids = [] self.channel_id = channel_id self.trainer_dict = {} - + def to_dict(self): if isinstance(self.location, POI): locid = str(self.location.id) @@ -105,13 +108,13 @@ def to_dict(self): 'message_ids': self.message_ids } return d - + @property def _data(self): table = self.bot.dbi.table('meetups') query = table.query.where(id=self.id) return query - + @property def _insert(self): table = self.bot.dbi.table('meetups') @@ -119,7 +122,7 @@ def _insert(self): d = self.to_dict() insert.row(**d) return insert - + async def upsert(self): insert = self._insert await insert.commit(do_update=True) @@ -127,7 +130,7 @@ async def upsert(self): @property def guild(self): return self.bot.get_guild(self.guild_id) - + @property def channel(self): return self.bot.get_channel(self.channel_id) @@ -135,7 +138,7 @@ def channel(self): @property def channel_topic(self): return "Use the ❔ button for help with commands you can use in this channel!" - + @property def time_str(self): hatchlocal = self.local_datetime(self.start) @@ -148,11 +151,11 @@ def time_str(self): enddatestr = endlocal.strftime('%b %d') topic_str += f"| Ends on {enddatestr} at {endtimestr}" return topic_str - + @property def report_channel(self): return self.bot.get_channel(self.report_channel_id) - + async def list_rsvp(self, channel, tags=False): color = self.guild.me.color trainer_dict = self.trainer_dict @@ -209,7 +212,7 @@ async def list_rsvp(self, channel, tags=False): return await channel.send(embed=embed) except: return - + async def list_teams(self, channel, tags=False): color = self.guild.me.color trainer_dict = self.trainer_dict @@ -259,7 +262,7 @@ async def list_teams(self, channel, tags=False): return await channel.send(embed=embed) except: return - + async def get_trainer_dict(self): def data(rcrd): trainer = rcrd['user_id'] @@ -279,7 +282,7 @@ def data(rcrd): trainer, rcrd_dict = data(rcrd) trainer_dict[trainer] = rcrd_dict return trainer_dict - + async def update_rsvp(self, user_id=None, status=None): self.trainer_dict = await self.get_trainer_dict() has_embed = False @@ -314,12 +317,12 @@ async def update_rsvp(self, user_id=None, status=None): await chn.send(embed=rsvpembed, delete_after=15) except: return - + @property def react_list(self): status_reacts = list(self.bot.config.emoji.values()) return status_reacts - + async def process_reactions(self, payload): if payload.guild_id: user = payload.member @@ -346,10 +349,10 @@ async def process_reactions(self, payload): await message.remove_reaction(emoji, user) if new_status != old_status: await meowthuser.meetup_rsvp(self, new_status, party=party) - + async def meetup_embed(self): return (await MeetupEmbed.from_meetup(self)).embed - + @staticmethod def status_dict(trainer_dict): d = { @@ -362,12 +365,12 @@ def status_dict(trainer_dict): status = trainer_dict[trainer]['status'] d[status] += total return d - + @property def status_str(self): status_str = self.status_string(self.bot, self.trainer_dict) return status_str - + @staticmethod def status_string(bot, trainer_dict): status_dict = Meetup.status_dict(trainer_dict) @@ -375,7 +378,7 @@ def status_string(bot, trainer_dict): status_str += f"{bot.config.emoji['coming']}: **{status_dict['coming']}** | " status_str += f"{bot.get_emoji(bot.config.emoji['here'])}: **{status_dict['here']}**" return status_str - + @staticmethod def team_dict(trainer_dict): d = { @@ -408,22 +411,22 @@ def team_string(bot, trainer_dict): team_str += f"{bot.config.team_emoji['valor']}: {team_dict['valor']} | " team_str += f"{bot.config.team_emoji['unknown']}: {team_dict['unknown']}" return team_str - + @property def current_local_datetime(self): zone = self.tz localzone = timezone(zone) return datetime.now(tz=localzone) - + def local_datetime(self, stamp): zone = self.tz localzone = timezone(zone) return datetime.fromtimestamp(stamp, tz=localzone) - + @property def start_datetime(self): return self.local_datetime(self.start) - + def update_time(self, new_time: float): if self.monitor_task: self.monitor_task.cancel() @@ -469,11 +472,6 @@ async def monitor_status(self): await asyncio.sleep(60) await self.channel.delete() - - - - - async def update_url(self, url): location = self.location if isinstance(location, POI): @@ -522,9 +520,7 @@ async def from_data(cls, bot, data): cls.by_message[msgid] = meetup return meetup - class Raid: - instances = dict() by_message = dict() by_channel = dict() @@ -563,16 +559,16 @@ def __init__(self, raid_id, bot, guild_id, report_channel_id, reporter_id, gym=N self.train_msgs = [] self._weather = "NO_WEATHER" self.completed_by = [] - + def __eq__(self, other): if isinstance(other, Raid): return self.id == other.id else: return False - + def __hash__(self): return hash(self.id) - + def to_dict(self): if isinstance(self.gym, Gym): gymid = str(self.gym.id) @@ -595,13 +591,13 @@ def to_dict(self): 'completed_by': self.completed_by } return d - + @property def _data(self): table = self.bot.dbi.table('raids') query = table.query.where(id=self.id) return query - + @property def _insert(self): table = self.bot.dbi.table('raids') @@ -609,11 +605,11 @@ def _insert(self): d = self.to_dict() insert.row(**d) return insert - + async def upsert(self): insert = self._insert await insert.commit(do_update=True) - + @property def status(self): if self.hatch and time.time() < self.hatch: @@ -624,7 +620,7 @@ def status(self): return "active" else: return "expired" - + @property def react_list(self): boss_reacts = formatters.mc_emoji(len(self.boss_list)) @@ -645,7 +641,7 @@ def react_list(self): react_list = react_list + grp_reacts react_list.append('\u2754') if self.status == 'active' or len(self.boss_list) == 1: - react_list.append(512707623812857871) + react_list.append(self.bot.config.pkbtlr_emoji['pkbtlr']) return react_list @property @@ -653,13 +649,13 @@ def max_hatch(self): level = self.level max_times = self.bot.raid_info.raid_times[level] return max_times[0] - + @property def max_active(self): level = self.level max_times = self.bot.raid_info.raid_times[level] return max_times[1] - + @property def guild(self): return self.bot.get_guild(self.guild_id) @@ -674,7 +670,7 @@ def reporter(self): @property def report_channel(self): return self.bot.get_channel(self.report_channel_id) - + def update_time(self, new_time: float): if self.monitor_task: self.monitor_task.cancel() @@ -710,7 +706,7 @@ def update_time(self, new_time: float): update.values(hatch=self.hatch, endtime=self.end) self.bot.loop.create_task(update.commit()) self.monitor_task = self.bot.loop.create_task(self.monitor_status()) - + async def get_boss_list(self): level = self.level report_channel = ReportChannel(self.bot, self.report_channel) @@ -718,7 +714,7 @@ async def get_boss_list(self): boss_list = list(boss_lists[level].keys()) self.boss_list = boss_list return boss_list - + async def boss_list_str(self, weather=None): boss_names = [] boss_list = await self.get_boss_list() @@ -742,9 +738,8 @@ async def boss_list_str(self, weather=None): name += ' :sparkles:' boss_names.append(f"{name} {type_emoji}: **{interest}**") boss_list_str = "\n".join(boss_names) - boss_list_str += "\n<:silph:548259248442703895>Boss list provided by [The Silph Road](https://thesilphroad.com/raid-bosses)" return boss_list_str - + @property def grps_str(self): ungrp = self.ungrp @@ -765,7 +760,7 @@ def grps_str(self): if ungrp_est != '0': grps_str.append(f"\u2754: ({ungrp_est}%)") return "\n".join(grps_str) + '\u200b' - + async def raidgroup_ask(self, channel, user): color = self.guild.me.color grps_str = self.grps_str @@ -787,18 +782,16 @@ async def raidgroup_ask(self, channel, user): if emoji == group['emoji']: await self.join_grp(payload.user_id, group) - - @property def grpd_users(self): return [x for y in self.group_list for x in y['users']] - + def user_grp(self, user): for grp in self.group_list: if user in grp['users']: return grp return None - + def grp_is_here(self, grp): for user in grp['users']: status = self.trainer_dict.get(user, {}).get('status') @@ -815,7 +808,7 @@ def ungrp(self): d['users'].append(x) d['est_power'] = self.grp_est_power(d) return d - + def grp_others(self, grp): d = {'users': []} for x in self.trainer_dict: @@ -826,7 +819,7 @@ def grp_others(self, grp): if len(d['users']) == 0: return None return d - + @property def coming_grp(self): d = {'users': [x for x in self.trainer_dict if self.trainer_dict[x]['status'] == 'coming']} @@ -846,14 +839,14 @@ def user_was_invited(self, user_id): if user_id in invites: return True return False - + def user_who_invited(self, user_id): for x in self.trainer_dict: invites = self.trainer_dict[x].get('invites', []) if user_id in invites: return x return None - + def user_invite_slots(self, user_id): invites = self.trainer_dict.get(user_id, {}).get('invites', []) return 5 - len(invites) @@ -864,34 +857,34 @@ def users_can_invite(self): users = [x for x in users if not self.user_was_invited(x)] users = [x for x in users if self.user_invite_slots(x) > 0] return users - + @property def users_need_invite(self): users = [x for x in self.trainer_dict if self.trainer_dict[x]['status'] == 'invite'] return users - + @property def pokebattler_url(self): pkmnid = self.pkmn.id url = f"https://www.pokebattler.com/raids/{pkmnid}" return url - + @staticmethod def pokebattler_data_url(pkmnid, level, att_level, weather): - if level == '7': + if level == '7' or level == '6': level = 'MEGA' json_url = 'https://fight2.pokebattler.com/raids/defenders/' json_url += f"{pkmnid}/levels/RAID_LEVEL_{level}/attackers/levels/" json_url += f"{att_level}/strategies/CINEMATIC_ATTACK_WHEN_POSSIBLE/" - json_url += f"DEFENSE_RANDOM_MC" + json_url += "DEFENSE_RANDOM_MC" json_url += f"?sort=ESTIMATOR&weatherCondition={weather}" json_url += "&dodgeStrategy=DODGE_REACTION_TIME" json_url += "&aggregation=AVERAGE&randomAssistants=-1" return json_url - + @staticmethod def user_pokebattler_data_url(pkmnid, level, pb_id, weather): - if level == '7': + if level == '7' or level == '6': level = 'MEGA' json_url = 'https://fight2.pokebattler.com/raids/defenders/' json_url += f"{pkmnid}/levels/RAID_LEVEL_{level}/attackers/users/" @@ -901,7 +894,7 @@ def user_pokebattler_data_url(pkmnid, level, pb_id, weather): json_url += "&dodgeStrategy=DODGE_REACTION_TIME" json_url += "&aggregation=AVERAGE&randomAssistants=-1" return json_url - + async def channel_name(self): if isinstance(self.gym, Gym): gym_name = await self.gym._name() @@ -911,7 +904,7 @@ async def channel_name(self): boss_name = await self.pkmn.name() return f"{boss_name}-{gym_name}" else: - if self.level == '7': + if self.level == '7' or self.level == '6': level_str = 'm' else: level_str = self.level @@ -920,7 +913,7 @@ async def channel_name(self): @property def channel_topic(self): return "Use the ❔ button for help with commands you can use in this channel!" - + @property def time_str(self): topic_str = "" @@ -940,13 +933,13 @@ def time_str(self): else: topic_str += f"Ends at {endtimestr}" return topic_str - + @property def current_local_datetime(self): zone = self.tz localzone = timezone(zone) return datetime.now(tz=localzone) - + def local_datetime(self, stamp): if not stamp: return None @@ -956,7 +949,7 @@ def local_datetime(self, stamp): else: localzone = timezone(zone) return datetime.fromtimestamp(stamp, tz=localzone) - + async def process_reactions(self, payload): if payload.guild_id: user = payload.member @@ -972,10 +965,11 @@ async def process_reactions(self, payload): new_status = None party = await meowthuser.party() if payload.emoji.is_custom_emoji(): - emoji = payload.emoji.id + emoji = str(payload.emoji.id) else: emoji = str(payload.emoji) - if emoji not in self.react_list: + status_reacts_temp = [re.sub('<:.*:','',sub).replace('>','').strip("'") for sub in self.react_list] + if emoji not in status_reacts_temp: return if isinstance(emoji, str): for group in self.group_list: @@ -993,7 +987,7 @@ async def process_reactions(self, payload): await message.remove_reaction(emoji, user) await self.leave_grp(payload.user_id) return await meowthuser.cancel_rsvp(self.id) - if emoji == 512707623812857871: + if emoji == re.sub('<:.*:','',self.bot.config.pkbtlr_emoji['pkbtlr']).replace('>','').strip("'"): if self.status != 'active': if len(self.boss_list) > 1: raise RaidNotActive @@ -1041,13 +1035,19 @@ async def process_reactions(self, payload): else: return await message.remove_reaction(emoji, user) for k, v in self.bot.config.emoji.items(): - if v == emoji: + if re.sub('<:.*:','',v).replace('>','').strip("'") == emoji: new_status = k new_bosses = [] else: return if isinstance(emoji, int): emoji = self.bot.get_emoji(emoji) + else: + try: + result = int(emoji) + emoji = self.bot.get_emoji(result) + except ValueError: + pass try: await message.remove_reaction(emoji, user) except: @@ -1056,7 +1056,7 @@ async def process_reactions(self, payload): return if new_bosses != old_bosses or new_status != old_status: await meowthuser.rsvp(self.id, new_status, bosses=new_bosses, party=party) - + async def start_grp(self, grp, author, channel=None): if channel: if not self.grp_is_here(grp): @@ -1146,7 +1146,7 @@ async def start_grp(self, grp, author, channel=None): grp_query.where(starttime=grp['starttime']) await grp_query.delete() await self.update_rsvp() - return + return def _rsvp(self, connection, pid, channel, payload): if channel != f'rsvp_{self.id}': @@ -1158,13 +1158,13 @@ def _rsvp(self, connection, pid, channel, payload): userid, status = payload.split('/') user_id = int(userid) event_loop.create_task(self.update_rsvp(user_id=user_id, status=status)) - + def _weather(self, connection, pid, channel, payload): if not isinstance(self.gym, Gym): return event_loop = asyncio.get_event_loop() event_loop.create_task(self.change_weather(payload)) - + async def change_weather(self, payload): if self.hatch and (self.hatch - time.time() > 3600): send = False @@ -1232,8 +1232,8 @@ async def change_weather(self, payload): try: await channel.send(content) except: - pass - + pass + async def join_grp(self, user_id, group, invite=False): old_rsvp = self.trainer_dict.get(user_id, {}) old_status = old_rsvp.get('status') @@ -1279,7 +1279,7 @@ async def join_grp(self, user_id, group, invite=False): if invites: for x in invites: await self.join_grp(x, group, invite=True) - + async def leave_grp(self, user_id): group_table = self.bot.dbi.table('raid_groups') insert = group_table.insert @@ -1305,7 +1305,7 @@ async def leave_grp(self, user_id): async def invite_ask(self, user_id): meowthuser = MeowthUser.from_id(self.bot, user_id) data = (await meowthuser._data.get())[0] - friendcode = data.get('friendcode') + #friendcode = data.get('friendcode') users_can_invite = self.users_can_invite if self.channel_ids: for chnid in self.channel_ids: @@ -1324,7 +1324,7 @@ async def invite_ask(self, user_id): payload = await formatters.ask(self.bot, [msg], user_list=users_can_invite, react_list=['✉']) if payload: return await self.raid_invite(payload.user_id, user_id) - + async def raid_invite(self, inviter_id, invitee_id): inviter = self.guild.get_member(inviter_id) if not inviter: @@ -1332,7 +1332,7 @@ async def raid_invite(self, inviter_id, invitee_id): invitee = self.guild.get_member(invitee_id) if not invitee: invitee = await self.guild.fetch_member(invitee_id) - inviter_name = inviter.display_name + #inviter_name = inviter.display_name invitee_name = invitee.display_name meowthinvitee = MeowthUser.from_id(self.bot, invitee_id) meowthinviter = MeowthUser.from_id(self.bot, inviter_id) @@ -1365,7 +1365,7 @@ async def raid_invite(self, inviter_id, invitee_id): await invitee.send(direct_invitee_content) if inviter_friendcode: await invitee.send(inviter_friendcode) - + async def notify_invite_users(self, user_id): invites = self.trainer_dict.get(user_id, {}).get('invites', []) if not invites: @@ -1386,7 +1386,7 @@ async def notify_invite_users(self, user_id): if not inviter: inviter = await self.guild.fetch_member(user_id) await inviter.send(content) - + async def update_rsvp(self, user_id=None, status=None, group=None): self.trainer_dict = await self.get_trainer_dict() @@ -1528,16 +1528,16 @@ async def monitor_status(self): self.hatch_task.cancel() elif self.expire_task: self.expire_task.cancel() - - + + async def weather(self): gym = self.gym if isinstance(gym, Gym): weather = await gym.weather() self._weather = weather return self._weather - + async def is_boosted(self, weather=None): if not weather: weather = await self.weather() @@ -1547,7 +1547,7 @@ async def is_boosted(self, weather=None): if len(boss_list) == 1: pkmn = RaidBoss(Pokemon(self.bot, boss_list[0])) return await pkmn.is_boosted(weather) - + async def cp_range(self, weather=None): boost = await self.is_boosted(weather=weather) pkmn = self.pkmn @@ -1568,7 +1568,7 @@ async def cp_range(self, weather=None): pkmn.staiv = 15 high_cp = await pkmn.calculate_cp() return [low_cp, high_cp] - + async def pb_data(self, weather=None): data_table = self.bot.dbi.table('counters_data') if not weather: @@ -1599,7 +1599,7 @@ async def pb_data(self, weather=None): return data[0] else: return None - + async def generic_counters_data(self, weather=None): data = await self.pb_data(weather=weather) if not data: @@ -1612,33 +1612,33 @@ async def generic_counters_data(self, weather=None): ctr = Pokemon(self.bot, ctrid, quickMoveid=ctrfast, chargeMoveid=ctrcharge) ctrs_list.append(ctr) return ctrs_list - + async def estimator_20(self, weather=None): data = await self.pb_data(weather=weather) if not data: return None estimator = data['estimator_20'] return estimator - + async def estimator_min(self, weather=None): data = await self.pb_data(weather=weather) if not data: return None estimator = data['estimator_min'] return estimator - + async def rec_group_size(self, weather=None): estimator = await self.estimator_20(weather=weather) if not estimator: return None return ceil(estimator) - + async def min_group_size(self): estimator = await self.estimator_min() if not estimator: return None return ceil(estimator) - + def user_est_power(self, user_id): trainer_dict = self.trainer_dict.get(user_id) if trainer_dict: @@ -1646,7 +1646,7 @@ def user_est_power(self, user_id): return est_power else: return 0 - + def grp_est_power(self, group): est = 0 users = group['users'] @@ -1660,7 +1660,7 @@ async def user_counters_data(self, user: MeowthUser): if not pkmn: boss_list = self.boss_list if len(boss_list) == 1: - pkmn = RaidBoss(Pokemon(self.bot, boss_list[0])) + pkmn = RaidBoss(Pokemon(self.bot, boss_list[0])) pkmnid = pkmn.id level = self.level if level == 'EX': @@ -1795,16 +1795,16 @@ async def set_moveset(self, move1, move2=None): async def egg_embed(self): return (await EggEmbed.from_raid(self)).embed - + async def counters_embed(self, user): countersembed = await CountersEmbed.from_raid(user, self) if not countersembed: return None return countersembed.embed - + async def hatched_embed(self): - raid_icon = 'https://media.discordapp.net/attachments/423492585542385664/512682888236367872/imageedit_1_9330029197.png' - footer_icon = 'https://media.discordapp.net/attachments/346766728132427777/512699022822080512/imageedit_10_6071805149.png' + raid_icon = 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_map.png' + footer_icon = 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_icon.png' level = self.level egg_img_url = self.bot.raid_info.egg_images[level] color = self.guild.me.color @@ -1858,14 +1858,21 @@ async def raid_embed(self): return (await RaidEmbed.from_raid(self)).embed def expired_embed(self): - embed = formatters.make_embed(content="This raid has expired!", footer="Expired") + raid_expire_grace_period = self.bot.config.raid_expire_grace_period + raid_expire_grace_time = self.end + convert_to_seconds(raid_expire_grace_period) + embed = formatters.make_embed(content="This raid and channel has expired!", footer="Raid and channel expired") + embed.timestamp = datetime.fromtimestamp(raid_expire_grace_time) + return embed + + def expired_grace_embed(self): + embed = formatters.make_embed(content="This raid has expired, channel will be deleted soon!", footer="Raid expired, channel will be removed soon") embed.timestamp = datetime.fromtimestamp(self.end) return embed - + async def report_embed(self): return (await ReportEmbed.from_raid(self)).embed - + async def update_url(self, url): gym = self.gym if isinstance(gym, Gym): @@ -1891,7 +1898,7 @@ async def update_url(self, url): except: pass elif (self.channel_ids or str(chn.id) in self.channel_ids) and self.status != 'expired': - if self.hatch and self.hatch > time.time(): + if self.hatch and self.hatch > time.time(): embed = await self.egg_embed() elif self.end > time.time(): embed = await self.raid_embed() @@ -1909,9 +1916,6 @@ async def update_url(self, url): await chn.send(content=content, embed=embed) except: pass - - - async def update_messages(self, content=''): msg_list = [] @@ -1919,10 +1923,16 @@ async def update_messages(self, content=''): react_list = self.react_list message_ids = self.message_ids train_msgs = self.train_msgs + + raid_expire_grace_period = self.bot.config.raid_expire_grace_period + raid_expire_grace_time = self.end + convert_to_seconds(raid_expire_grace_period) + if self.hatch and self.hatch > time.time(): embed = await self.egg_embed() elif self.end > time.time(): embed = await self.raid_embed() + elif time.time() > self.end and time.time() < raid_expire_grace_time: + embed = self.expired_grace_embed() else: embed = self.expired_embed() for messageid in message_ids: @@ -1940,6 +1950,7 @@ async def update_messages(self, content=''): msg_list.append(msg) continue try: + embed.timestamp = embed.timestamp await msg.edit(content=content, embed=embed) except Exception as e: continue @@ -1986,8 +1997,6 @@ async def update_messages(self, content=''): await msg.add_reaction(react) return msg_list - - async def hatch_egg(self): try: if self.end < time.time(): @@ -2081,8 +2090,6 @@ async def hatch_egg(self): except: pass - - async def report_hatch(self, pkmn): trainer_dict = self.trainer_dict int_list = [] @@ -2105,7 +2112,7 @@ async def report_hatch(self, pkmn): if mention: mention_list.append(mention) name = await self.pkmn.name() - content = f"Trainers {' '.join(mention_list)}: The egg has hatched into a {name} raid!" + content = f"Trainers {' '.join(mention_list)}: The egg has hatched into a {name} raid!" raid_table = self.bot.dbi.table('raids') update = raid_table.update() update.where(id=self.id) @@ -2124,12 +2131,11 @@ async def correct_weather(self, weather): await self.gym.correct_weather(weather.value) else: await self.change_weather(weather.value) - - - async def expire_raid(self): try: + self.bot.loop.create_task(self.update_messages()) + await asyncio.sleep(convert_to_seconds(self.bot.config.raid_expire_grace_period)) self.bot.loop.create_task(self.update_messages()) await asyncio.sleep(60) try: @@ -2203,7 +2209,7 @@ async def expire_raid(self): self.bot.loop.create_task(grps.delete()) except asyncio.CancelledError: raise - + async def archive_raid(self, channel, user_id, reason=None): guild = channel.guild bot = self.bot @@ -2232,13 +2238,11 @@ async def archive_raid(self, channel, user_id, reason=None): except: pass - - # async def update_gym(self, gym): async def get_wants(self): wants = [] - if self.level == '7': + if self.level == '7' or self.level == '6': wants.append('mega') else: wants.append(self.level) @@ -2258,8 +2262,6 @@ async def get_wants(self): want_dict = {x: await x.mention() for x in wants} return want_dict - - async def boss_interest_dict(self): boss_list = self.boss_list d = {x: 0 for x in boss_list} @@ -2290,20 +2292,20 @@ def status_dict(trainer_dict): if status and status != 'cancel': d[status] += total return d - + @property def status_str(self): status_str = self.status_string(self.bot, self.trainer_dict) return status_str - + @staticmethod def status_string(bot, trainer_dict): status_dict = Raid.status_dict(trainer_dict) status_str = f"{bot.config.emoji['maybe']}: **{status_dict['maybe'] + status_dict['invite']}** | " status_str += f"{bot.config.emoji['coming']}: **{status_dict['coming']}** | " - status_str += f"{bot.get_emoji(bot.config.emoji['here'])}: **{status_dict['here'] + status_dict['remote']}**" + status_str += f"{bot.config.emoji['here']}: **{status_dict['here'] + status_dict['remote']}**" return status_str - + @staticmethod def team_dict(trainer_dict): d = { @@ -2338,7 +2340,7 @@ def team_string(bot, trainer_dict): team_str += f"{bot.config.team_emoji['valor']}: {team_dict['valor']} | " team_str += f"{bot.config.team_emoji['unknown']}: {team_dict['unknown']}" return team_str - + def grp_status_dict(self, group): d = { 'maybe': 0, @@ -2354,7 +2356,7 @@ def grp_status_dict(self, group): status = trainer_dict[trainer]['status'] d[status] += total return d - + def grp_total(self, group): total = 0 trainer_dict = self.trainer_dict @@ -2363,17 +2365,17 @@ def grp_total(self, group): return total def grp_remotes(self, group): - total = 0 + #total = 0 status_dict = self.grp_status_dict(group) return status_dict.get('remote', 0) - + def grp_status_str(self, group): status_dict = self.grp_status_dict(group) status_str = f"{self.bot.config.emoji['maybe']}: {status_dict['maybe'] + status_dict['invite']} | " status_str += f"{self.bot.config.emoji['coming']}: {status_dict['coming']} | " status_str += f"{self.bot.get_emoji(self.bot.config.emoji['here'])}: {status_dict['here'] + status_dict['remote']}" return status_str - + def grp_team_dict(self, group): d = { 'mystic': 0, @@ -2392,7 +2394,7 @@ def grp_team_dict(self, group): d['valor'] += redcount d['unknown'] += unknowncount return d - + def grp_team_str(self, group): team_dict = self.grp_team_dict(group) team_str = f"{self.bot.config.team_emoji['mystic']}: {team_dict['mystic']} | " @@ -2420,7 +2422,7 @@ async def get_grp_list(self): grp['est_power'] = self.grp_est_power(grp) group_list.append(grp) return group_list - + async def list_rsvp(self, channel, tags=False): color = self.guild.me.color trainer_dict = self.trainer_dict @@ -2511,7 +2513,7 @@ async def list_invites(self, channel): await self.raid_invite(inviter_id, invitee_id) else: break - + async def list_teams(self, channel, tags=False): color = self.guild.me.color trainer_dict = self.trainer_dict @@ -2555,7 +2557,7 @@ async def list_teams(self, channel, tags=False): return await channel.send(f'Current Raid Team Totals\n\n{liststr}') embed = formatters.make_embed(title="Current Raid Team Totals", content=liststr, msg_colour=color) return await channel.send(embed=embed) - + async def list_groups(self, channel, tags=False): color = self.guild.me.color liststr = "" @@ -2589,7 +2591,7 @@ async def list_groups(self, channel, tags=False): return await channel.send(f'Current Raid Groups\n\n{liststr}') embed = formatters.make_embed(title="Current Raid Groups", content=liststr, msg_colour=color) return await channel.send(embed=embed) - + async def list_bosses(self, channel, tags=False): color = self.guild.me.color trainer_dict = self.trainer_dict @@ -2703,8 +2705,8 @@ async def from_data(cls, bot, data): raid.completed_by = completed_by await raid.get_boss_list() return raid - - + + async def summary_str(self): if self.status == 'egg': pre_str = f'**Level {self.level} Raid at' @@ -2779,7 +2781,7 @@ def __init__(self, train_id, bot, guild_id, channel_id, report_channel_id): self.multi_msg_ids = [] self.message_ids = [] self.trainer_dict = {} - + def to_dict(self): d = { 'id': self.id, @@ -2794,13 +2796,13 @@ def to_dict(self): 'message_ids': self.message_ids } return d - + @property def _data(self): table = self.bot.dbi.table('trains') query = table.query.where(id=self.id) return query - + @property def _insert(self): table = self.bot.dbi.table('trains') @@ -2812,15 +2814,15 @@ def _insert(self): async def upsert(self): insert = self._insert await insert.commit(do_update=True) - + @property def guild(self): return self.bot.get_guild(self.guild_id) - + @property def channel(self): return self.bot.get_channel(self.channel_id) - + async def messages(self): for msgid in self.message_ids: chn, msg = await ChannelMessage.from_id_string(self.bot, msgid) @@ -2828,12 +2830,12 @@ async def messages(self): yield msg else: continue - + @property def report_channel(self): rchan = self.bot.get_channel(self.report_channel_id) return ReportChannel(self.bot, rchan) - + async def report_msgs(self): for msgid in self.report_msg_ids: try: @@ -2842,7 +2844,7 @@ async def report_msgs(self): yield msg except: continue - + async def clear_reports(self): async for msg in self.report_msgs(): try: @@ -2850,7 +2852,7 @@ async def clear_reports(self): except: pass self.report_msg_ids = [] - + async def multi_msgs(self): for msgid in self.multi_msg_ids: chn, msg = await ChannelMessage.from_id_string(self.bot, msgid) @@ -2858,7 +2860,7 @@ async def multi_msgs(self): yield msg else: continue - + async def clear_multis(self): async for msg in self.multi_msgs(): try: @@ -2866,13 +2868,13 @@ async def clear_multis(self): except: pass self.multi_msg_ids = [] - + async def reported_raids(self): for msgid in self.report_msg_ids: raid = Raid.by_trainreport.get(msgid) msg = await self.channel.fetch_message(msgid) yield (msg, raid) - + async def report_results(self): async for msg, raid in self.reported_raids(): reacts = msg.reactions @@ -2881,13 +2883,13 @@ async def report_results(self): continue count = react.count yield (raid, count) - + async def possible_raids(self): idlist = await self.report_channel.get_all_raids() raid_list = [Raid.instances.get(x) for x in idlist if Raid.instances.get(x)] raid_list = [x for x in raid_list if x.level != 'EX'] return raid_list - + async def select_raid(self, raid): if not raid: await self.end_train() @@ -2924,7 +2926,7 @@ async def select_raid(self, raid): self.next_raid = None await self.upsert() self.bot.loop.create_task(self.poll_next_raid()) - + async def finish_current_raid(self): raid = self.current_raid if raid: @@ -3051,13 +3053,13 @@ async def select_first_raid(self, author): multi = await self.report_channel.channel.send(content, embed=embed) content = "" self.multi_msg_ids.append(f'{self.report_channel_id}/{multi.id}') - payload = await formatters.ask(self.bot, [multi], user_list=[author.id], + payload = await formatters.ask(self.bot, [multi], user_list=[author.id], react_list=react_list) choice_dict = dict(zip(react_list, raids)) first_raid = choice_dict[str(payload.emoji)] await self.clear_multis() await self.select_raid(first_raid) - + async def poll_next_raid(self): raids = await self.possible_raids() if self.current_raid: @@ -3072,7 +3074,7 @@ async def poll_next_raid(self): self.multi_msg_ids.append(f'{self.channel_id}/{multi.id}') await self.upsert() self.poll_task = self.bot.loop.create_task(self.get_poll_results(multi, raids, react_list)) - + async def get_poll_results(self, multi, raids, react_list): results = None if multi: @@ -3102,12 +3104,12 @@ async def get_poll_results(self, multi, raids, react_list): return choice_dict[str(emoji)] else: return - + async def display_choices(self, raids, react_list): color = self.guild.me.color dest_dict = {} eggs_list = [] - hatched_list = [] + #hatched_list = [] active_list = [] if self.current_raid: if isinstance(self.current_raid.gym, Gym): @@ -3184,7 +3186,7 @@ async def route_url(self, next_raid): return await next_raid.gym.url() else: return next_raid.gym.url - + async def new_raid(self, raid: Raid): embed = await TRaidEmbed.from_raid(self, raid) content = "Use the reaction below to vote for this raid next!" @@ -3197,7 +3199,7 @@ async def new_raid(self, raid: Raid): raid.train_msgs.append(f'{msg.channel.id}/{msg.id}') await msg.add_reaction('\u2b06') await self.upsert() - + async def update_rsvp(self, user_id, status): self.trainer_dict = await self.get_trainer_dict() has_embed = False @@ -3207,7 +3209,7 @@ async def update_rsvp(self, user_id, status): train_embed.team_str = self.team_str await msg.edit(embed=train_embed.embed) channel = self.channel - guild = channel.guild + #guild = channel.guild if status == 'join': status_str = ' has joined the train!' elif status == 'cancel': @@ -3219,7 +3221,7 @@ async def update_rsvp(self, user_id, status): if not self.trainer_dict: await self.end_train() - + async def end_train(self): try: await self.channel.send('This train is now empty! This channel will be deleted in one minute.') @@ -3283,7 +3285,7 @@ async def archive_train(self, channel, user_id, reason): for row in data: embed = formatters.deleted_message_embed(self.bot, row) await channel.send(embed=embed) - + async def train_embed(self): return await TrainEmbed.from_train(self) @@ -3330,8 +3332,8 @@ class ReportEmbed(): def __init__(self, embed): self.embed = embed - - raid_icon = 'https://media.discordapp.net/attachments/423492585542385664/512682888236367872/imageedit_1_9330029197.png' #TODO + + raid_icon = 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_map.png' boss_index = 0 gym_index = 1 @@ -3353,12 +3355,12 @@ async def from_raid(cls, raid: Raid): img_url = await boss.sprite_url() else: bossfield = "Level" - if raid.level == '7': + if raid.level == '7' or raid.level == '6': name = 'Mega' else: name = raid.level img_url = raid.bot.raid_info.egg_images[raid.level] - enddt = datetime.fromtimestamp(raid.hatch) + #enddt = datetime.fromtimestamp(raid.hatch) # color = await boss.color() gym = raid.gym if isinstance(gym, Gym): @@ -3396,7 +3398,7 @@ class RaidEmbed(): def __init__(self, embed): self.embed = embed - raid_icon = 'https://media.discordapp.net/attachments/423492585542385664/512682888236367872/imageedit_1_9330029197.png' #TODO + raid_icon = 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_map.png' boss_index = 0 gym_index = 1 @@ -3422,32 +3424,32 @@ def set_boss(self, boss_dict): self.embed.set_field_at(RaidEmbed.cp_index, name="CP Range", value=cp_str) self.embed.set_field_at(RaidEmbed.moveset_index, name="Moveset", value=moveset_str) return self - + def set_weather(self, weather, cp_str, ctrs_str, rec_str=None): self.embed.set_field_at(RaidEmbed.cp_index, name="CP Range", value=cp_str) if rec_str: self.embed.set_field_at(RaidEmbed.rec_index, name="Recommended Group Size", value=rec_str) self.embed.set_footer(text=self.embed.footer.text, icon_url=weather.icon_url) return self - + def set_moveset(self, moveset_str, ctrs_str, rec_str=None): self.embed.set_field_at(RaidEmbed.moveset_index, name="Moveset", value=moveset_str) if rec_str: self.embed.set_field_at(RaidEmbed.rec_index, name="Recommended Group Size", value=rec_str) return self - + @property def status_str(self): return self.embed.fields[RaidEmbed.status_index].value - + @status_str.setter def status_str(self, status_str): self.embed.set_field_at(RaidEmbed.status_index, name="Status List", value=status_str) - + @property def team_str(self): return self.embed.fields[RaidEmbed.team_index].value - + @team_str.setter def team_str(self, team_str): self.embed.set_field_at(RaidEmbed.team_index, name="Team List", value=team_str) @@ -3455,15 +3457,15 @@ def team_str(self, team_str): @property def rec_str(self): return self.embed.fields[RaidEmbed.rec_index].value - + @rec_str.setter def rec_str(self, rec_str): self.embed.set_field_at(RaidEmbed.rec_index, name="Recommended Group Size", value=rec_str) - + @property def grps_str(self): return self.embed.fields[RaidEmbed.group_index].value - + @grps_str.setter def grps_str(self, grps_tuple): self.embed.set_field_at(RaidEmbed.group_index, name=grps_tuple[0], value=grps_tuple[1]) @@ -3499,7 +3501,7 @@ async def from_raid(cls, raid: Raid): is_boosted = await boss.is_boosted(weather.value) cp_range = await raid.cp_range() cp_str = f"{cp_range[0]}-{cp_range[1]}" - end = raid.end + #end = raid.end if is_boosted: cp_str += " (Boosted)" img_url = await boss.sprite_url() @@ -3551,12 +3553,11 @@ async def from_raid(cls, raid: Raid): return cls(embed) class RSVPEmbed(): - def __init__(self, embed): self.embed = embed - raid_icon = 'https://media.discordapp.net/attachments/423492585542385664/512682888236367872/imageedit_1_9330029197.png' #TODO - footer_icon = 'https://media.discordapp.net/attachments/346766728132427777/512699022822080512/imageedit_10_6071805149.png' + raid_icon = 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_map.png' + footer_icon = 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_icon.png' status_index = 0 team_index = 1 @@ -3564,19 +3565,19 @@ def __init__(self, embed): @property def status_str(self): return self.embed.fields[RSVPEmbed.status_index].value - + @status_str.setter def status_str(self, status_str): self.embed.set_field_at(RSVPEmbed.status_index, name="Status List", value=status_str) - + @property def team_str(self): return self.embed.fields[RSVPEmbed.team_index].value - + @team_str.setter def team_str(self, team_str): self.embed.set_field_at(RSVPEmbed.team_index, name="Team List", value=team_str) - + @classmethod def from_meetup(cls, meetup: Meetup): @@ -3593,12 +3594,9 @@ def from_meetup(cls, meetup: Meetup): embed = formatters.make_embed(title="Current RSVP Totals", fields=fields, footer=footer, msg_colour=color) return cls(embed) - + @classmethod def from_raid(cls, raid: Raid): - - - status_str = raid.status_str team_str = raid.team_str footer = raid.time_str @@ -3612,10 +3610,9 @@ def from_raid(cls, raid: Raid): embed = formatters.make_embed(icon=RSVPEmbed.raid_icon, title="Current RSVP Totals", fields=fields, footer_icon=RSVPEmbed.footer_icon, footer=footer, msg_colour=color) return cls(embed) - + @classmethod def from_raidgroup(cls, raid: Raid, group): - status_str = raid.grp_status_str(group) team_str = raid.grp_team_str(group) est = group.get('est_power', 0) @@ -3635,14 +3632,13 @@ def from_raidgroup(cls, raid: Raid, group): else: embed.add_field(name='Starting', value=time, inline=False) return cls(embed) - -class EggEmbed(): +class EggEmbed(): def __init__(self, embed): self.embed = embed - - raid_icon = 'https://media.discordapp.net/attachments/423492585542385664/512682888236367872/imageedit_1_9330029197.png' - + + raid_icon = 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_map.png' + level_index = 0 status_index = 2 team_index = 3 @@ -3654,48 +3650,45 @@ def set_weather(self, weather, boss_list_str): self.boss_str = boss_list_str self.embed.set_footer(text=self.embed.footer.text, icon_url=weather.icon_url) return self - + @property def status_str(self): return self.embed.fields[EggEmbed.status_index].value - + @status_str.setter def status_str(self, status_str): self.embed.set_field_at(EggEmbed.status_index, name="Status List", value=status_str) - + @property def team_str(self): return self.embed.fields[EggEmbed.team_index].value - + @team_str.setter def team_str(self, team_str): self.embed.set_field_at(EggEmbed.team_index, name="Team List", value=team_str) - + @property def boss_str(self): return self.embed.fields[EggEmbed.boss_list_index].value - + @boss_str.setter def boss_str(self, boss_str): self.embed.set_field_at(EggEmbed.boss_list_index, name="Boss Interest", value=boss_str) - + @property def grps_str(self): return self.embed.fields[EggEmbed.group_index].value - + @grps_str.setter def grps_str(self, grps_tuple): self.embed.set_field_at(EggEmbed.group_index, name=grps_tuple[0], value=grps_tuple[1], inline=False) - - - @classmethod async def from_raid(cls, raid: Raid): level = raid.level egg_img_url = raid.bot.raid_info.egg_images[level] # color = await formatters.url_color(egg_img_url) - hatch = raid.hatch + #hatch = raid.hatch gym = raid.gym if isinstance(gym, Gym): directions_url = await gym.url() @@ -3713,7 +3706,7 @@ async def from_raid(cls, raid: Raid): status_str = raid.status_str team_str = raid.team_str boss_str = await raid.boss_list_str() - if level == '7': + if level == '7' or level == '6': level_str = 'Mega' else: level_str = level @@ -3739,12 +3732,11 @@ async def from_raid(cls, raid: Raid): return cls(embed) class CountersEmbed(): - def __init__(self, embed): self.embed = embed - - raid_icon = 'https://media.discordapp.net/attachments/423492585542385664/512682888236367872/imageedit_1_9330029197.png' #TODO - footer_icon = 'https://media.discordapp.net/attachments/346766728132427777/512699022822080512/imageedit_10_6071805149.png' + + raid_icon = 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_map.png' + footer_icon = 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_icon.png' boss_index = 0 weather_index = 1 @@ -3790,7 +3782,7 @@ async def from_raid(cls, user: MeowthUser, raid: Raid): cp_range = await raid.cp_range() cp_str = f"{cp_range[0]}-{cp_range[1]}" end = raid.end - enddt = datetime.fromtimestamp(end) + #enddt = datetime.fromtimestamp(end) if is_boosted: cp_str += " (Boosted)" img_url = await boss.sprite_url() @@ -3824,30 +3816,29 @@ async def from_raid(cls, user: MeowthUser, raid: Raid): ctrs_str.append(ctr_str) i += 1 ctrs_str.append(f'[Results courtesy of Pokebattler](https://www.pokebattler.com/raids/{boss.id})') - fields['<:pkbtlr:512707623812857871> Counters'] = "\n".join(ctrs_str) + fields[bot.config.pkbtlr_emoji['pkbtlr'] + ' Counters'] = "\n".join(ctrs_str) color = raid.guild.me.color embed = formatters.make_embed(icon=CountersEmbed.raid_icon, thumbnail=img_url, msg_colour=color, fields=fields, footer_icon=CountersEmbed.footer_icon) return cls(embed) class TrainEmbed(): - def __init__(self, embed): self.embed = embed - + title = "Raid Train" - current_raid_index = 1 + current_raid_index = 1 team_index = 2 channel_index = 0 @property def team_str(self): return self.embed.fields[TrainEmbed.team_index].value - + @team_str.setter def team_str(self, team_str): self.embed.set_field_at(TrainEmbed.team_index, name="Team List", value=team_str) - + @classmethod async def from_train(cls, train: Train): title = cls.title @@ -3867,12 +3858,11 @@ async def from_train(cls, train: Train): return cls(embed) class TRSVPEmbed(): - def __init__(self, embed): self.embed = embed - + title = 'Current Train Totals' - + @classmethod def from_train(cls, train: Train): title = cls.title @@ -3884,13 +3874,10 @@ def from_train(cls, train: Train): embed = formatters.make_embed(title=title, fields=fields, msg_colour=color) return cls(embed) - - class TRaidEmbed(): - def __init__(self, embed): self.embed = embed - + @classmethod async def from_raid(cls, train: Train, raid: Raid): if raid.status == 'active': @@ -3908,8 +3895,8 @@ async def from_raid(cls, train: Train, raid: Raid): name = raid.level img_url = raid.bot.raid_info.egg_images[name] bot = raid.bot - end = raid.end - enddt = datetime.fromtimestamp(end) + #end = raid.end + #enddt = datetime.fromtimestamp(end) color = raid.guild.me.color gym = raid.gym travel_time = "Unknown" @@ -3941,29 +3928,28 @@ async def from_raid(cls, train: Train, raid: Raid): return cls(embed) class MeetupEmbed: - def __init__(self, embed): self.embed = embed - + status_index = 1 team_index = 2 @property def status_str(self): return self.embed.fields[MeetupEmbed.status_index].value - + @status_str.setter def status_str(self, status_str): self.embed.set_field_at(MeetupEmbed.status_index, name="Status List", value=status_str) - + @property def team_str(self): return self.embed.fields[MeetupEmbed.team_index].value - + @team_str.setter def team_str(self, team_str): self.embed.set_field_at(MeetupEmbed.team_index, name="Team List", value=team_str) - + @classmethod async def from_meetup(cls, meetup: Meetup): location = meetup.location diff --git a/meowth/exts/raid/raid_cog.py b/meowth/exts/raid/raid_cog.py index 2681e0e4b..ba85f20d6 100644 --- a/meowth/exts/raid/raid_cog.py +++ b/meowth/exts/raid/raid_cog.py @@ -15,10 +15,6 @@ from .objects import Raid, RaidBoss, Train, Meetup from math import ceil -import discord -from discord.ext import commands -from discord import Embed -from discord import app_commands import asyncio import aiohttp import time @@ -27,6 +23,10 @@ from pytz import timezone import typing import re +import discord +from discord.ext import commands +from discord import Embed +from discord import app_commands emoji_letters = ['🇦','🇧','🇨','🇩','🇪','🇫','🇬','🇭','🇮','🇯','🇰','🇱', '🇲','🇳','🇴','🇵','🇶','🇷','🇸','🇹','🇺','🇻','🇼','🇽','🇾','🇿' @@ -120,7 +120,15 @@ async def get_raid_lists(self): "5": {}, "6": {}, "EX": {}, - "7": {} + "7": {}, + "8": {}, + "9": {}, + "10": {}, + "11": {}, + "12": {}, + "13": {}, + "14": {}, + "15": {} } table = self.bot.dbi.table('raid_bosses') query = table.query @@ -139,7 +147,9 @@ def data(rcrd): return level, boss_id, d for rcrd in rows: level, boss_id, d = data(rcrd) - raid_lists[level][boss_id] = d + + if d.get("available"): + raid_lists[level][boss_id] = d return raid_lists async def archive_cat_phrases(self, guild): @@ -489,13 +499,11 @@ async def raid(self, ctx, level_or_boss, *, gym_and_time): mention = channel.mention mentions.append(mention) if mentions: - return await ctx.send(f"""There is already a raid reported at this gym! Coordinate here: {", ".join(mentions)}""", embed=embed) + return await ctx.send(f'There is already a raid reported at this gym! Coordinate here: {", ".join(mentions)}', embed=embed) else: - msg = await ctx.send(f"""There is already a raid reported at this gym! Coordinate here!""", embed=embed) + msg = await ctx.send("There is already a raid reported at this gym! Coordinate here!", embed=embed) old_raid.message_ids.append(f"{msg.channel.id}/{msg.id}") return msg - if level_or_boss in ['m', '7']: - level_or_boss = '7' if level_or_boss.isdigit(): level = level_or_boss boss = None @@ -517,6 +525,60 @@ async def raid(self, ctx, level_or_boss, *, gym_and_time): ctx.raid = new_raid return await self.setup_raid(ctx, new_raid) + async def raid_slash_command_bot(self, message, boss: str, gym: str, minutes_remaining: app_commands.Range[int, 1, 45]=45): + ctx = await self.bot.get_context(message, cls=Context) + class Object(object): + pass + a = Object() + a.name = 'raid' + ctx.command = a + ctx.author = message.author + try: + await raid_checks.is_raid_enabled(ctx) + await raid_checks.check_bot_permissions(ctx) + await checks.check_location_set(ctx) + except Exception as e: + self.bot.dispatch('command_error', ctx, e) + return + zone = await ctx.tz() + gym = await Gym.convert(ctx, gym) + + raid_table = ctx.bot.dbi.table('raids') + if isinstance(gym, Gym): + query = raid_table.query() + query.where(gym=str(gym.id), guild=ctx.guild.id) + old_raid = await query.get() + if old_raid: + old_raid = old_raid[0] + old_raid = await Raid.from_data(ctx.bot, old_raid) + if old_raid.level != 'EX': + if old_raid.hatch: + embed = await old_raid.egg_embed() + else: + embed = await old_raid.raid_embed() + if old_raid.channel_ids: + mentions = [] + for channelid in old_raid.channel_ids: + channel = ctx.guild.get_channel(int(channelid)) + if not channel: + continue + mention = channel.mention + mentions.append(mention) + if mentions: + return await ctx.send(f'There is already a raid reported at this gym! Coordinate here: {", ".join(mentions)}', embed=embed) + else: + msg = await ctx.send("There is already a raid reported at this gym! Coordinate here!", embed=embed) + old_raid.message_ids.append(f"{msg.channel.id}/{msg.id}") + return msg + raid_boss = await RaidBoss.convert(ctx, boss) + level = await raid_boss.raid_level() + hatch = None + end = time.time() + 60*minutes_remaining + raid_id = next(snowflake.create()) + new_raid = Raid(raid_id, self.bot, message.guild.id, message.channel.id, message.author.id, gym, level=level, pkmn=raid_boss, hatch=hatch, end=end, tz=zone) + ctx.raid = new_raid + return await self.setup_raid(ctx, new_raid) + async def raid_slash_command(self, interaction: discord.Interaction, boss: str, gym: str, minutes_remaining: app_commands.Range[int, 1, 45]=45): message = await interaction.original_message() ctx = await self.bot.get_context(message, cls=Context) @@ -557,9 +619,9 @@ class Object(object): mention = channel.mention mentions.append(mention) if mentions: - return await ctx.send(f"""There is already a raid reported at this gym! Coordinate here: {", ".join(mentions)}""", embed=embed) + return await ctx.send(f'There is already a raid reported at this gym! Coordinate here: {", ".join(mentions)}', embed=embed) else: - msg = await ctx.send(f"""There is already a raid reported at this gym! Coordinate here!""", embed=embed) + msg = await ctx.send("There is already a raid reported at this gym! Coordinate here!", embed=embed) old_raid.message_ids.append(f"{msg.channel.id}/{msg.id}") return msg raid_boss = await RaidBoss.convert(ctx, boss) @@ -571,11 +633,59 @@ class Object(object): ctx.raid = new_raid return await self.setup_raid(ctx, new_raid) + async def egg_slash_command_bot(self, message, level: str, gym: str, minutes_to_hatch: app_commands.Range[int, 1, 60]): + ctx = await self.bot.get_context(message, cls=Context) + zone = await ctx.tz() + ctx.author = message.author + + try: + await raid_checks.is_raid_enabled(ctx) + await raid_checks.check_bot_permissions(ctx) + await checks.check_location_set(ctx) + except Exception as e: + self.bot.dispatch('command_error', ctx, e) + return + gym = await Gym.convert(ctx, gym) + raid_table = ctx.bot.dbi.table('raids') + if isinstance(gym, Gym): + query = raid_table.query() + query.where(gym=str(gym.id), guild=ctx.guild.id) + old_raid = await query.get() + if old_raid: + old_raid = old_raid[0] + old_raid = await Raid.from_data(ctx.bot, old_raid) + if old_raid.level != 'EX': + if old_raid.hatch: + embed = await old_raid.egg_embed() + else: + embed = await old_raid.raid_embed() + if old_raid.channel_ids: + mentions = [] + for channelid in old_raid.channel_ids: + channel = ctx.guild.get_channel(int(channelid)) + if not channel: + continue + mention = channel.mention + mentions.append(mention) + if mentions: + return await ctx.send(f'There is already a raid reported at this gym! Coordinate here: {", ".join(mentions)}', embed=embed) + else: + msg = await ctx.send("There is already a raid reported at this gym! Coordinate here!", embed=embed) + old_raid.message_ids.append(f"{msg.channel.id}/{msg.id}") + return msg + hatch = time.time() + 60*minutes_to_hatch + end = hatch + 60*ctx.bot.raid_info.raid_times[level][1] + raid_id = next(snowflake.create()) + new_raid = Raid(raid_id, self.bot, message.guild.id, message.channel.id, message.author.id, gym, level=level, hatch=hatch, end=end, tz=zone) + ctx.raid = new_raid + return await self.setup_raid(ctx, new_raid) + async def egg_slash_command(self, interaction: discord.Interaction, level: str, gym: str, minutes_to_hatch: app_commands.Range[int, 1, 60]): message = await interaction.original_message() ctx = await self.bot.get_context(message, cls=Context) zone = await ctx.tz() ctx.author = interaction.user + try: await raid_checks.is_raid_enabled(ctx) await raid_checks.check_bot_permissions(ctx) @@ -606,9 +716,9 @@ async def egg_slash_command(self, interaction: discord.Interaction, level: str, mention = channel.mention mentions.append(mention) if mentions: - return await ctx.send(f"""There is already a raid reported at this gym! Coordinate here: {", ".join(mentions)}""", embed=embed) + return await ctx.send(f'There is already a raid reported at this gym! Coordinate here: {", ".join(mentions)}', embed=embed) else: - msg = await ctx.send(f"""There is already a raid reported at this gym! Coordinate here!""", embed=embed) + msg = await ctx.send("There is already a raid reported at this gym! Coordinate here!", embed=embed) old_raid.message_ids.append(f"{msg.channel.id}/{msg.id}") return msg hatch = time.time() + 60*minutes_to_hatch @@ -1142,7 +1252,7 @@ async def level(self, ctx, *, level): """Correct the raid level in an existing raid channel. Usable only by mods.""" - possible_levels = ['1', '2', '3', '4', '5', 'EX', '7'] + possible_levels = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', 'EX'] if level not in possible_levels: return raid = Raid.by_channel.get(str(ctx.channel.id)) diff --git a/meowth/exts/raid/raid_commands.py b/meowth/exts/raid/raid_commands.py index 3248ef49f..1cd5e44d6 100644 --- a/meowth/exts/raid/raid_commands.py +++ b/meowth/exts/raid/raid_commands.py @@ -1,4 +1,4 @@ -from typing import List, Literal +from typing import List import discord from discord import app_commands @@ -9,7 +9,7 @@ class RaidCommands(app_commands.Group): def __init__(self): super().__init__(name='raid', description='Report Pokemon Go raids') - + async def on_error(self, interaction, command, error): raise error.original @@ -17,13 +17,15 @@ async def boss_autocomplete( self, interaction: discord.Interaction, current: str, namespace: app_commands.Namespace ) -> List[app_commands.Choice[str]]: bot = interaction.client + shadow_emoji = bot.config.form_emoji['shadow'] raid_cog = bot.get_cog('RaidCog') raid_lists = await raid_cog.get_raid_lists() boss_list = [x for y in raid_lists.values() for x in list(y.keys())] pkmn_list = [await Pokemon(bot, x).name() for x in boss_list] + pkmn_list_clean = [x.replace(f"{str(shadow_emoji)}","- Shadow") for x in pkmn_list] return [ app_commands.Choice(name=boss, value=boss) - for boss in pkmn_list if current.lower() in boss.lower() + for boss in pkmn_list_clean if current.lower() in boss.lower() ][:25] async def gym_autocomplete( @@ -46,14 +48,12 @@ async def raid_slash_command(self, interaction: discord.Interaction, boss: str, raid_cog = bot.get_cog('RaidCog') boss = boss.replace(' ', '').replace('(', ' (') return await raid_cog.raid_slash_command(interaction, boss, gym, minutes_remaining) - + @app_commands.command(name='egg') @app_commands.describe(level='the raid level', gym='the raid gym', minutes_to_hatch='whole number of minutes to hatch') @app_commands.autocomplete(gym=gym_autocomplete) - async def egg_slash_command(self, interaction: discord.Interaction, level: Literal['1', '3', '5', '7'], gym: str, minutes_to_hatch: app_commands.Range[int, 1, 60]=60): + async def egg_slash_command(self, interaction: discord.Interaction, level: app_commands.Range[int, 1, 15], gym: str, minutes_to_hatch: app_commands.Range[int, 1, 60]=60): await interaction.response.send_message('Thanks for your report!', ephemeral=True) bot = interaction.client raid_cog = bot.get_cog('RaidCog') - return await raid_cog.egg_slash_command(interaction, level, gym, minutes_to_hatch) - - \ No newline at end of file + return await raid_cog.egg_slash_command(interaction, str(level), gym, minutes_to_hatch) diff --git a/meowth/exts/raid/raid_info.py b/meowth/exts/raid/raid_info.py index 1a5df685a..4668928cf 100644 --- a/meowth/exts/raid/raid_info.py +++ b/meowth/exts/raid/raid_info.py @@ -6,30 +6,54 @@ '5': (60, 45), '6': (60, 45), "EX": (None, 45), - '7': (60, 45) + '7': (60, 45), + '8': (60, 45), + '9': (60, 45), + '10': (60, 45), + '11': (60, 45), + '12': (60, 45), + '13': (60, 45), + '14': (60, 45), + '15': (60, 45) } egg_images = { - '1': 'https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_normal.png', - '2': 'https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_normal.png', - '3': 'https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_rare.png', - '4': 'https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_rare.png', - '5': 'https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_legendary.png', - '6': 'https://raw.githubusercontent.com/ZeChrales/PogoAssets/master/static_assets/png/ic_raid_egg_legendary.png', - 'EX': 'https://github.com/ZeChrales/PogoAssets/blob/master/static_assets/png/Item_1403.png?raw=true', - '7': 'https://github.com/ZeChrales/PogoAssets/blob/master/decrypted_assets/png/raid_egg_3_icon.png?raw=true' - + '1': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_1.png', + '2': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_2.png', + '3': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_3.png', + '4': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_4.png', + '5': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_5.png', + '6': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_6.png', + '7': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_7.png', + '8': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_8.png', + '9': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_9.png', + '10': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_10.png', + '11': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_11.png', + '12': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_12.png', + '13': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_13.png', + '14': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_14.png', + '15': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/raid_egg_15.png', + 'EX': 'https://raw.githubusercontent.com/jackyaz/Meowth/self-host/meowth/images/misc/Item_1403.png' } raid_lists = { - '1': ["MAGIKARP", "DRATINI", "SWABLU", "FEEBAS", "SHINX", "BUIZEL"], - '2': ["EXEGGUTOR_ALOLA_FORM", "KIRLIA", "SABLEYE", "MAWILE"], - '3': ["ALAKAZAM", "MACHAMP", "AZUMARILL", "GRANBULL"], - '4': ["MAROWAK_ALOLA_FORM", "TOGETIC", "URSARING", "TYRANITAR", "ABSOL"], - '5': ["PALKIA"], + '1': [], + '2': [], + '3': [], + '4': [], + '5': [], '6': [], - "EX": ["DEOXYS_ATTACK_FORM"] + "EX": [], + '7': [], + '8': [], + '9': [], + '10': [], + '11': [], + '12': [], + '13': [], + '14': [], + '15': [], } -status_can_invite = ['coming', 'here', 'remote'] # remote will be removed eventually -max_remotes = 10 # will change to 5 eventually \ No newline at end of file +status_can_invite = ['coming', 'here', 'remote'] +max_remotes = 10 diff --git a/meowth/exts/research/research_cog.py b/meowth/exts/research/research_cog.py index 3b23b46e8..8418c19dc 100644 --- a/meowth/exts/research/research_cog.py +++ b/meowth/exts/research/research_cog.py @@ -461,7 +461,6 @@ async def on_raw_reaction_add(self, payload): choice_dict = dict(zip(react_list, pkmn_dict.values())) display_dict = dict(zip(react_list, pkmn_dict.keys())) embed = formatters.mc_embed(display_dict) - embed.fields[0].value = embed.fields[0].value + "\n<:silph:548259248442703895>Research tasks and rewards provided by [The Silph Road](https://thesilphroad.com/research-tasks)" multi = await chn.send(f"{user.mention}: What is the reward for this task? Please select from the options below. If you don't know, just ignore this!", embed=embed) payload = await formatters.ask(self.bot, [multi], user_list=[user.id], @@ -677,7 +676,6 @@ def check(m): choice_dict = dict(zip(react_list, reward_dict.values())) display_dict = dict(zip(react_list, reward_dict.keys())) embed = formatters.mc_embed(display_dict) - embed.fields[0].value = embed.fields[0].value + "\n<:silph:548259248442703895>Research tasks and rewards provided by [The Silph Road](https://thesilphroad.com/research-tasks)" multi = await ctx.send('What is the reward for this task? Please select from the options below.', embed=embed) payload = await formatters.ask(ctx.bot, [multi], user_list=[ctx.author.id], @@ -863,7 +861,7 @@ async def from_research(cls, research): elif reward == 'unknown_encounter': desc = "Unknown Encounter" thumbnail = ("https://raw.githubusercontent.com/" - "FoglyOgly/Meowth/new-core/meowth/images/misc/unknown_encounter.png") + "jackyaz/Meowth/self-host/meowth/images/misc/unknown_encounter.png") else: pkmn = Pokemon(bot, reward) desc = await pkmn.name() @@ -884,7 +882,7 @@ async def from_research(cls, research): fields = { 'Pokestop': f"[{directions_text}]({directions_url})", 'Task': task, - 'Reward': desc + "\n<:silph:548259248442703895>Research tasks and rewards provided by [The Silph Road](https://thesilphroad.com/research-tasks)" + 'Reward': desc } reporter = research.guild.get_member(research.reporter_id) if not reporter: @@ -894,7 +892,7 @@ async def from_research(cls, research): reporter_avy = reporter.display_avatar.url footer = f"Reported by {reporter_name} • Expires" icon_url = ("https://raw.githubusercontent.com/" - "FoglyOgly/Meowth/new-core/meowth/images/misc/field-research.png") + "jackyaz/Meowth/self-host/meowth/images/misc/field-research.png") embed = formatters.make_embed(title=title, thumbnail=thumbnail, fields=fields, footer=footer, footer_icon=reporter_avy, icon=icon_url, msg_colour=color) embed.timestamp = datetime.utcfromtimestamp(research.expires_at) diff --git a/meowth/exts/rocket/rocket_cog.py b/meowth/exts/rocket/rocket_cog.py index c9d99dd0f..1b20f17bf 100644 --- a/meowth/exts/rocket/rocket_cog.py +++ b/meowth/exts/rocket/rocket_cog.py @@ -126,7 +126,7 @@ def name(self): def img_url(self): url = ("https://raw.githubusercontent.com/" - "FoglyOgly/Meowth/new-core/meowth/images/misc/") + "jackyaz/Meowth/self-host/meowth/images/misc/") url += f"{self.kind.name.lower()}.png" return url diff --git a/meowth/exts/silph/__init__.py b/meowth/exts/silph/__init__.py deleted file mode 100644 index f6ff47c24..000000000 --- a/meowth/exts/silph/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .silph_cog import SilphCog - -def setup(bot): - bot.add_cog(SilphCog(bot)) \ No newline at end of file diff --git a/meowth/exts/silph/errors.py b/meowth/exts/silph/errors.py deleted file mode 100644 index f7dd4b77e..000000000 --- a/meowth/exts/silph/errors.py +++ /dev/null @@ -1,18 +0,0 @@ -from discord.ext.commands import CommandError - -class InvalidAPIKey(CommandError): - 'Exception raised, invalid Silph API Key' - pass - -class SilphCardNotFound(CommandError): - 'Exception raised, Silph Card not found' - pass - -class SilphCardPrivate(CommandError): - 'Exception raised, Silph Card private' - pass - -class SilphCardAlreadyLinked(CommandError): - 'Exception raised, Silph Card linked to different user' - pass - diff --git a/meowth/exts/silph/objects.py b/meowth/exts/silph/objects.py deleted file mode 100644 index c3c38013f..000000000 --- a/meowth/exts/silph/objects.py +++ /dev/null @@ -1,295 +0,0 @@ - -import datetime -import dateparser -import aiohttp - -import discord -from discord.ext import commands -from meowth.utils import formatters, fuzzymatch -from meowth.exts.users import MeowthUser -from .errors import * - -class SilphBadge: - - __slots__ = ('count', '_awarded', 'slug', 'name', 'description', 'image_url') - - def __init__(self, data): - self.count = data.get('count') - badge_info = data.get('Badge', {}) - self.slug = badge_info.get('slug') - self.name = badge_info.get('name') - self.description = badge_info.get('description') - self.image_url = badge_info.get('image_url') - self._awarded = data.get('awarded') - - def __str__(self): - return self.name - - def __repr__(self): - type_name = type(self).__name__ - name = self.name - created = self.awarded() - return f"<{type_name} name='{name}' awarded='{created}'>" - - def awarded(self, utc_offset=None): - if not self._awarded: - return None - date = dateparser.parse(self._awarded, settings={'TIMEZONE': 'UTC'}) - if utc_offset: - date = date + datetime.timedelta(hours=utc_offset) - return date.date().isoformat() - -class SilphCheckin: - - __slots__ = ('name', 'description', 'image_url', '_is_global', '_start', - '_end', '_created') - - def __init__(self, data): - self.name = data.get('name') - self.description = data.get('description') - self.image_url = data.get('image') - self._is_global = data.get('is_global') - event_checkin_data = data.get('EventCheckin', {}) - self._created = event_checkin_data.get('created') - - def __str__(self): - return self.name - - def __repr__(self): - type_name = type(self).__name__ - name = self.name - created = self.created() - return f"<{type_name} name='{name}' created='{created}'>" - - @property - def is_global(self): - if not self._is_global: - return None - return formatters.convert_to_bool(self._is_global) - - def created(self, utc_offset=None): - if not self._created: - return None - date = dateparser.parse(self._created, settings={'TIMEZONE': 'UTC'}) - if utc_offset: - date = date + datetime.timedelta(hours=utc_offset) - return date.date().isoformat() - -class SilphCard: - - __slots__ = ('id', 'home_region', 'team', 'title', 'playstyle', 'level', - 'avatar_url', 'silph_name', 'game_name', 'url', - 'data_url', '_badges', '_top_6_pokemon', '_nest_migrations', - '_pokedex_count', '_xp', '_raid_average', '_goal', '_joined', - '_modified', '_connected_accounts', '_checkins', '_handshakes') - - def __init__(self, silph_username, data): - data = data.get('data', data) - self.silph_name = silph_username - self.game_name = data.get('in_game_username') - self.data_url = f'https://sil.ph/{silph_username}.json' - self.url = f'https://sil.ph/{silph_username}' - self.id = data.get('card_id') - self.home_region = data.get('home_region') - self.team = data.get('team') - self.title = data.get('title') - self.playstyle = data.get('playstyle') - self.level = data.get('trainer_level') - self.avatar_url = data.get('avatar') - self._badges = data.get('badges') - self._top_6_pokemon = data.get('top_6_pokemon') - self._nest_migrations = data.get('nest_migrations') - self._pokedex_count = data.get('pokedex_count') - self._xp = data.get('xp') - self._raid_average = data.get('raid_average') - self._handshakes = data.get('handshakes') - self._goal = data.get('goal') - self._joined = data.get('joined') - self._modified = data.get('modified') - self._connected_accounts = data.get('socials') - self._checkins = data.get('checkins') - - def __str__(self): - return f"{self.id} - {self.silph_name}" - - def __repr__(self): - type_name = type(self).__name__ - name = self.silph_name - ign = self.game_name - return f"<{type_name} id='{self.id}' silph_name='{name}' ign='{ign}'>" - - def get_connected_account(self, vendor): - con_acc = self._connected_accounts - search = (acc for acc in con_acc if acc.get('vendor') == vendor) - return next(search, None) - - @property - def badges(self): - if not self._badges: - return None - return tuple(SilphBadge(b) for b in self._badges) - - @property - def badge_count(self): - if not self._badges: - return 0 - return len(self._badges) - - @property - def checkins(self): - if not self._badges: - return None - return tuple(SilphCheckin(c) for c in self._checkins) - - @property - def checkin_count(self): - if not self._badges: - return 0 - return len(self._checkins) - - @property - def top_pkmn(self): - if not self._top_6_pokemon: - return None - return tuple(self._top_6_pokemon) - - @property - def migrations(self): - return int(self._nest_migrations) if self._nest_migrations else 0 - - @property - def pd_count(self): - return int(self._pokedex_count) if self._pokedex_count else 0 - - @property - def xp(self): - return int(self._xp) if self._xp else 0 - - @property - def raid_avg(self): - return int(self._raid_average) if self._raid_average else 0 - - @property - def handshakes(self): - return int(self._handshakes) if self._handshakes else 0 - - @property - def goal(self): - return self._goal.lower() if self._goal else None - - @property - def discord_name(self): - data = self.get_connected_account('Discord') - return data.get('username') if data else None - - def joined(self): - if not self._joined: - return None - date = dateparser.parse(self._joined, settings={'TIMEZONE': 'UTC'}) - return date.date().isoformat() - - def modified(self, utc_offset=None): - if not self._modified: - return None - date = dateparser.parse(self._modified, settings={'TIMEZONE': 'UTC'}) - return date - - def embed(self): - - colour = discord.Colour(0xe8c13c) - hyperlink_icon = "https://i.imgur.com/fn9E5nb.png" - silph_icon = "https://assets.thesilphroad.com/img/snoo_sr_icon.png" - - if not self.discord_name: - connected_str = "\u2754 **Discord Not Provided**" - else: - connected_str = ( - f"\u2611 **Connected to Discord:** {self.discord_name}") - - embed = discord.Embed( - title='Playstyle', colour=colour, description=( - f"{self.playstyle}, working on {self.goal}.\n" - f"Active around {self.home_region}.\n\n" - f"{connected_str}")) - - embed.set_thumbnail(url=self.avatar_url) - - embed.set_author( - name=( - f"{self.title} {self.game_name} - " - f"Level {self.level} {self.team}"), - url=self.url, - icon_url=hyperlink_icon) - - embed.add_field( - name="__Silph Stats__", - value=( - f"**Joined:** {self.joined()}\n" - f"**Badges:** {self.badge_count}\n" - f"**Check-ins:** {self.checkin_count}\n" - f"**Handshakes:** {self.handshakes}\n" - f"**Migrations:** {self.migrations}"), - inline=True) - - embed.add_field( - name="__Game Stats__", - value=( - f"**Name:** {self.game_name}\n" - f"**Team:** {self.team}\n" - f"**Level:** {self.level}\n" - f"**Pokedex:** {self.pd_count}\n" - f"**Raids:** {self.raid_avg}/week"), - inline=True) - - embed.set_footer( - text=( - f"Silph Road Travelers Card - ID{self.id} - " - f"Updated"), - icon_url=silph_icon) - - embed.timestamp = self.modified() - - return embed - - @classmethod - async def get_trainer_card(cls, silph_user): - url = f'https://sil.ph/{silph_user}.json' - async with aiohttp.ClientSession() as sess: - async with sess.get(url) as resp: - data = await resp.json() - if data.get('error', None): - error = data['error'] - if error == "Card not found": - raise SilphCardNotFound - elif error == "Private Travelers Card": - raise SilphCardPrivate - else: - return None - return cls(silph_user, data) - -class SilphTrainer: - def __init__(self, silph_user): - self.name = silph_user - self.card = None - - async def load_card_data(self): - self.card = await SilphCard.get_trainer_card(self.name) - return self.card - - @classmethod - async def load_trainer_data(cls, silph_user): - instance = cls(silph_user) - await instance.load_card_data() - return instance - - @classmethod - async def convert(cls, ctx, arg): - try: - meowth_user = await MeowthUser.convert(ctx, arg) - silph_id = await meowth_user.silph() - except: - meowth_user = None - if not meowth_user: - silph_id = arg - return await cls.load_trainer_data(silph_id) - \ No newline at end of file diff --git a/meowth/exts/silph/silph_cog.py b/meowth/exts/silph/silph_cog.py deleted file mode 100644 index 59a6136b3..000000000 --- a/meowth/exts/silph/silph_cog.py +++ /dev/null @@ -1,229 +0,0 @@ -from meowth import Cog, command, bot, checks -from meowth.exts.users import MeowthUser, users_checks - -import asyncio -import aiohttp -import time -from datetime import datetime -from dateparser import parse - -from . import silph_info -from .objects import SilphTrainer -from .errors import * - -class SilphCog(Cog): - - def __init__(self, bot): - self.bot = bot - - def parse_tasks_from_silph(self, data): - rows = [] - all_verified = True - for r in data: - task = r['title'] - rewards = r['rewards'] - pkmn_rewards = rewards.get('pokemon', []) - item_rewards = rewards.get('items', {}) - for pkmn in pkmn_rewards: - if not pkmn['pokemon']: - continue - slug = pkmn['pokemon']['slug'] - meowthid = slug.upper().replace('-', '_') - if meowthid == 'GIRATINA_ALTERED': - meowthid = 'GIRATINA' - forms = ['ALOLA', 'ATTACK', 'DEFENSE', 'SPEED', 'RAINY', 'SNOWY', 'SUNNY', 'ORIGIN', 'PLANT', 'SANDY', 'TRASH', 'GALAR'] - for form in forms: - if meowthid.endswith(form): - if form == 'GALAR': - meowthid += "IAN" - meowthid += "_FORM" - if meowthid.endswith('_M'): - meowthid += "ALE" - elif meowthid.endswith('_F'): - meowthid += "EMALE" - row = { - 'task': task, - 'reward': meowthid - } - rows.append(row) - for item in item_rewards: - amount = item_rewards[item] - itemstr = f"{item}/{amount}" - row = { - 'task': task, - 'reward': itemstr - } - rows.append(row) - return rows, all_verified - - - def parse_info_from_silph(self, data): - rows = [] - all_verified = True - for level in data: - if level == 'LEVEL_6': - new_level = 'EX' - else: - new_level = level[-1] - for boss in data[level]['boss']: - silphid = boss['id'] - available = boss['available'] - verified = boss['verified'] - if not verified: - all_verified = False - shiny = boss['shiny'] - meowthid = silphid.upper().replace('-', '_') - if meowthid == 'GIRATINA_ALTERED': - meowthid = 'GIRATINA' - forms = ['ALOLA', 'ATTACK', 'DEFENSE', 'SPEED', 'RAINY', 'SNOWY', 'SUNNY', 'ORIGIN', 'PLANT', 'SANDY', 'TRASH', 'ARMOR', 'GALAR'] - for form in forms: - if meowthid.endswith(form): - if form == 'ARMOR': - meowthid = "MEWTWO_A" - if form == 'GALAR': - meowthid += "IAN" - meowthid += "_FORM" - if meowthid.endswith('_M'): - meowthid += "ALE" - elif meowthid.endswith('_F'): - meowthid += "EMALE" - d = { - 'level': new_level, - 'pokemon_id': meowthid, - 'verified': verified, - 'available': available, - 'shiny': shiny - } - rows.append(d) - return rows, all_verified - - @Cog.listener() - async def on_command_error(self, ctx, error): - if isinstance(error, InvalidAPIKey): - return await ctx.error("Invalid Silph API Key") - elif isinstance(error, SilphCardNotFound): - return await ctx.error("Silph Card Not Found") - elif isinstance(error, SilphCardPrivate): - return await ctx.error("Silph Card Private") - elif isinstance(error, SilphCardAlreadyLinked): - return await ctx.error("Silph Card Linked to Another Discord") - - @command() - @users_checks.users_enabled() - async def silph(self, ctx, silph_name: SilphTrainer): - """Link your Silph Road account.""" - - silph_id = silph_name - silph_card = silph_id.card - linked_discord = silph_card.discord_name - if not linked_discord == str(ctx.author): - raise SilphCardAlreadyLinked - meowthuser = MeowthUser(ctx.bot, ctx.author) - data = await meowthuser._data.get() - if len(data) == 0: - insert = meowthuser._insert - d = {'id': ctx.author.id, 'silph': silph_id.name} - insert.row(**d) - await insert.commit() - else: - update = meowthuser._update - update.values(silph=silph_id.name) - await update.commit() - return await ctx.success(f'Silph ID set to {silph_id.name}') - - @command() - async def silphcard(self, ctx, silph_user: SilphTrainer = None): - """Displays a user's Silph Road Trainer Card.""" - if not silph_user: - user_id = ctx.author.id - meowth_user = MeowthUser.from_id(ctx.bot, user_id) - silph_id = await meowth_user.silph() - if not silph_id: - return await ctx.error(f"You haven't setup a silphcard!") - silph_user = await SilphTrainer.load_trainer_data(silph_id) - card = silph_user.card - if card: - await ctx.send(embed=card.embed()) - else: - await ctx.error(f'Silph Card for {silph_user} not found.') - - @command() - @checks.is_co_owner() - async def shakeup(self, ctx, *, shaketime=None): - i = 0 - if shaketime: - newdt = parse(shaketime, settings={'TIMEZONE': 'America/Chicago', 'RETURN_AS_TIMEZONE_AWARE': True}) - stamp = newdt.timestamp() - sleeptime = stamp - time.time() - else: - sleeptime = 0 - await asyncio.sleep(sleeptime) - url = 'https://api.thesilphroad.com/v0/raids' - headers = {'Authorization': f'Silph {silph_info.api_key}'} - while True: - async with aiohttp.ClientSession() as sess: - async with sess.get(url, headers=headers) as resp: - data = await resp.json(content_type=None) - data = data['data'] - rows, verified = self.parse_info_from_silph(data) - table = ctx.bot.dbi.table('raid_bosses') - if verified and i >= 60: - query = table.query - await query.delete() - insert = table.insert - insert.rows(rows) - await insert.commit(do_update=True) - if not verified or i < 60: - await asyncio.sleep(60) - i += 1 - continue - break - await ctx.success('Boss shakeup complete') - - @command() - @checks.is_co_owner() - async def replace(self, ctx): - url = 'https://api.thesilphroad.com/v0/raids' - headers = {'Authorization': f'Silph {silph_info.api_key}'} - async with aiohttp.ClientSession() as sess: - async with sess.get(url, headers=headers) as resp: - try: - data = await resp.json(content_type=None) - except: - return - table = ctx.bot.dbi.table('raid_bosses') - query = table.query - await query.delete() - data = data['data'] - rows, verified = self.parse_info_from_silph(data) - insert = table.insert - insert.rows(rows) - await insert.commit(do_update=True) - await ctx.success('Bosses replaced') - - @command() - @checks.is_co_owner() - async def tasksupdate(self, ctx): - url = 'https://api.thesilphroad.com/v0/research/tasks' - headers = {'Authorization': f'Silph {silph_info.api_key}'} - while True: - async with aiohttp.ClientSession() as sess: - async with sess.get(url, headers=headers) as resp: - try: - data = await resp.json() - except: - return await ctx.send('Failed') - table = ctx.bot.dbi.table('research_tasks') - insert = table.insert - query = table.query - data = data['data'] - rows, verified = self.parse_tasks_from_silph(data) - if verified: - await query.delete() - insert.rows(rows) - await insert.commit(do_update=True) - if not verified: - await asyncio.sleep(300) - continue - break - await ctx.success('New tasks verified') \ No newline at end of file diff --git a/meowth/exts/silph/silph_info.py b/meowth/exts/silph/silph_info.py deleted file mode 100644 index 760aef26e..000000000 --- a/meowth/exts/silph/silph_info.py +++ /dev/null @@ -1 +0,0 @@ -api_key = # API key goes here \ No newline at end of file diff --git a/meowth/exts/trade/trade_cog.py b/meowth/exts/trade/trade_cog.py index 259f7ca10..7f57d4fff 100644 --- a/meowth/exts/trade/trade_cog.py +++ b/meowth/exts/trade/trade_cog.py @@ -37,7 +37,7 @@ def __init__(self, trade_id, bot, guild_id, lister_id, listing_id, offered_pkmn, self.wanted_pkmn = wanted_pkmn self.offer_list = [] - icon_url = 'https://github.com/FoglyOgly/Meowth/blob/new-core/meowth/images/misc/trade_icon_small.png?raw=true' + icon_url = 'https://github.com/jackyaz/Meowth/blob/self-host/meowth/images/misc/trade_icon_small.png?raw=true' @classmethod def from_data(cls, bot, data): diff --git a/meowth/exts/tutorial/tutorial_cog.py b/meowth/exts/tutorial/tutorial_cog.py index 7f9123405..e59ad593b 100644 --- a/meowth/exts/tutorial/tutorial_cog.py +++ b/meowth/exts/tutorial/tutorial_cog.py @@ -496,6 +496,16 @@ async def tutorial(self, ctx): d['category_3'] = 'message' d['category_4'] = 'message' d['category_5'] = 'message' + d['category_6'] = 'message' + d['category_7'] = 'message' + d['category_8'] = 'message' + d['category_9'] = 'message' + d['category_10'] = 'message' + d['category_11'] = 'message' + d['category_12'] = 'message' + d['category_13'] = 'message' + d['category_14'] = 'message' + d['category_15'] = 'message' d['category_ex'] = 'message' d['lat'] = -90 d['lon'] = 0 @@ -713,6 +723,16 @@ async def raid(self, ctx): 'category_3': 'message', 'category_4': 'message', 'category_5': 'message', + 'category_6': 'message', + 'category_7': 'message', + 'category_8': 'message', + 'category_9': 'message', + 'category_10': 'message', + 'category_11': 'message', + 'category_12': 'message', + 'category_13': 'message', + 'category_14': 'message', + 'category_15': 'message', 'category_ex': 'message' } report_channel_table = ctx.bot.dbi.table('report_channels') diff --git a/meowth/exts/users/users_cog.py b/meowth/exts/users/users_cog.py index c67d82c7d..1b32ea74e 100644 --- a/meowth/exts/users/users_cog.py +++ b/meowth/exts/users/users_cog.py @@ -66,12 +66,6 @@ async def pokebattler(self): data.select('pokebattler') pbid = await data.get_value() return pbid - - async def silph(self): - data = self._data - data.select('silph') - silphid = await data.get_value() - return silphid async def ign(self): data = self._data @@ -95,11 +89,6 @@ async def set_pokebattler(self, pb_id): update.values(pokebattler=pb_id) await update.commit() - async def set_silph(self, silph): - update = self._update - update.values(silph=silph) - await update.commit() - async def party(self): data = self._data data.select('party') diff --git a/meowth/exts/want/want_cog.py b/meowth/exts/want/want_cog.py index 403d0e75d..a8657f2df 100644 --- a/meowth/exts/want/want_cog.py +++ b/meowth/exts/want/want_cog.py @@ -25,7 +25,7 @@ async def name(self): @property def img_url(self): url = ("https://raw.githubusercontent.com/" - "FoglyOgly/Meowth/new-core/meowth/images/misc/") + "jackyaz/Meowth/self-host/meowth/images/misc/") url += self.id url += '.png' return url @@ -217,7 +217,7 @@ async def role(self): continue members.append(member) members = [x for x in members if x] - raid_tiers = ['1', '2', '3', '4', '5', 'EX', 'MEGA'] + raid_tiers = ['1', '2', '3', '4', '5', '8', '9', '10', '11', '12', '13', '14', '15', 'EX', 'MEGA'] if self.want.startswith('FAMILY'): pokemon_table = self.bot.dbi.table('pokemon') pokemon_query = pokemon_table.query('pokemonid') @@ -290,7 +290,7 @@ async def convert(cls, ctx, arg): lures = ['glacial', 'mossy', 'magnetic'] if arg in lures: return cls(ctx.bot, arg, ctx.guild.id) - tiers = ['1', '2', '3', '4', '5', 'ex', 'exgym', 'mega', 'm'] + tiers = ['1', '2', '3', '4', '5', '8', '9', '10', '11', '12', '13', '14', '15', 'ex', 'exgym', 'mega', 'm'] if arg in tiers: if arg == 'm': arg = 'mega' diff --git a/meowth/exts/weather/weather_cog.py b/meowth/exts/weather/weather_cog.py index 075bb1add..5f03f33dc 100644 --- a/meowth/exts/weather/weather_cog.py +++ b/meowth/exts/weather/weather_cog.py @@ -33,20 +33,24 @@ async def name(self): return name async def types_boosted(self): - types_table = self.bot.dbi.table('types') - query = types_table.select('typeid').where(weather=self.value) - type_list = await query.get_values() + type_list = [] + + for pkmn_type in self.bot.config.type_emoji.values(): + if(pkmn_type.get("weather") == self.value): + type_list.append(pkmn_type.get("typeid")) + return type_list async def boosted_emoji_str(self): - types_table = self.bot.dbi.table('types') - query = types_table.query('emoji').where(weather=self.value) - emoji_list = await query.get_values() + emoji_list = [] + for pkmn_type in self.bot.config.type_emoji.values(): + if(pkmn_type.get("weather") == self.value): + emoji_list.append(pkmn_type.get("emoji")) return "".join(emoji_list) @property def icon_url(self): - url = f'https://github.com/FoglyOgly/Meowth/blob/new-core/meowth/images/weather/{self.value}.png?raw=true' + url = f'https://github.com/jackyaz/Meowth/blob/self-host/meowth/images/weather/{self.value}.png?raw=true' return url @property diff --git a/meowth/exts/wild/wild_cog.py b/meowth/exts/wild/wild_cog.py index 6a581b70c..b39317087 100644 --- a/meowth/exts/wild/wild_cog.py +++ b/meowth/exts/wild/wild_cog.py @@ -412,7 +412,7 @@ def name(self): def img_url(self): url = ("https://raw.githubusercontent.com/" - "FoglyOgly/Meowth/new-core/meowth/images/misc/") + "jackyaz/Meowth/self-host/meowth/images/misc/") url += f"{self.kind}.png" return url diff --git a/meowth/images/misc/raid_egg_1.png b/meowth/images/misc/raid_egg_1.png new file mode 100644 index 000000000..ea4ff1ba1 Binary files /dev/null and b/meowth/images/misc/raid_egg_1.png differ diff --git a/meowth/images/misc/raid_egg_10.png b/meowth/images/misc/raid_egg_10.png new file mode 100644 index 000000000..84708312d Binary files /dev/null and b/meowth/images/misc/raid_egg_10.png differ diff --git a/meowth/images/misc/raid_egg_11.png b/meowth/images/misc/raid_egg_11.png new file mode 100644 index 000000000..737056413 Binary files /dev/null and b/meowth/images/misc/raid_egg_11.png differ diff --git a/meowth/images/misc/raid_egg_12.png b/meowth/images/misc/raid_egg_12.png new file mode 100644 index 000000000..737056413 Binary files /dev/null and b/meowth/images/misc/raid_egg_12.png differ diff --git a/meowth/images/misc/raid_egg_13.png b/meowth/images/misc/raid_egg_13.png new file mode 100644 index 000000000..cc6fb162c Binary files /dev/null and b/meowth/images/misc/raid_egg_13.png differ diff --git a/meowth/images/misc/raid_egg_14.png b/meowth/images/misc/raid_egg_14.png new file mode 100644 index 000000000..cc6fb162c Binary files /dev/null and b/meowth/images/misc/raid_egg_14.png differ diff --git a/meowth/images/misc/raid_egg_15.png b/meowth/images/misc/raid_egg_15.png new file mode 100644 index 000000000..b7221623b Binary files /dev/null and b/meowth/images/misc/raid_egg_15.png differ diff --git a/meowth/images/misc/raid_egg_2.png b/meowth/images/misc/raid_egg_2.png new file mode 100644 index 000000000..ea4ff1ba1 Binary files /dev/null and b/meowth/images/misc/raid_egg_2.png differ diff --git a/meowth/images/misc/raid_egg_3.png b/meowth/images/misc/raid_egg_3.png new file mode 100644 index 000000000..de71c6876 Binary files /dev/null and b/meowth/images/misc/raid_egg_3.png differ diff --git a/meowth/images/misc/raid_egg_4.png b/meowth/images/misc/raid_egg_4.png new file mode 100644 index 000000000..aed221eb1 Binary files /dev/null and b/meowth/images/misc/raid_egg_4.png differ diff --git a/meowth/images/misc/raid_egg_5.png b/meowth/images/misc/raid_egg_5.png new file mode 100644 index 000000000..48e1b47f1 Binary files /dev/null and b/meowth/images/misc/raid_egg_5.png differ diff --git a/meowth/images/misc/raid_egg_6.png b/meowth/images/misc/raid_egg_6.png new file mode 100644 index 000000000..b2d7e9da3 Binary files /dev/null and b/meowth/images/misc/raid_egg_6.png differ diff --git a/meowth/images/misc/raid_egg_7.png b/meowth/images/misc/raid_egg_7.png new file mode 100644 index 000000000..66c1d036f Binary files /dev/null and b/meowth/images/misc/raid_egg_7.png differ diff --git a/meowth/images/misc/raid_egg_8.png b/meowth/images/misc/raid_egg_8.png new file mode 100644 index 000000000..69d8ee677 Binary files /dev/null and b/meowth/images/misc/raid_egg_8.png differ diff --git a/meowth/images/misc/raid_egg_9.png b/meowth/images/misc/raid_egg_9.png new file mode 100644 index 000000000..ff065740d Binary files /dev/null and b/meowth/images/misc/raid_egg_9.png differ diff --git a/meowth/images/misc/raid_logo.png b/meowth/images/misc/raid_logo.png new file mode 100644 index 000000000..a84a786e2 Binary files /dev/null and b/meowth/images/misc/raid_logo.png differ diff --git a/meowth/images/misc/raid_map.png b/meowth/images/misc/raid_map.png new file mode 100644 index 000000000..66577143e Binary files /dev/null and b/meowth/images/misc/raid_map.png differ diff --git a/meowth/images/misc/uptime.png b/meowth/images/misc/uptime.png new file mode 100644 index 000000000..3f83c94a2 Binary files /dev/null and b/meowth/images/misc/uptime.png differ diff --git a/meowth/images/pkmn/PAWMI.png b/meowth/images/pkmn/PAWMI.png new file mode 100644 index 000000000..a9da8f6db Binary files /dev/null and b/meowth/images/pkmn/PAWMI.png differ diff --git a/meowth/images/pkmn/PAWMI_SHINY.png b/meowth/images/pkmn/PAWMI_SHINY.png new file mode 100644 index 000000000..3ef960b5e Binary files /dev/null and b/meowth/images/pkmn/PAWMI_SHINY.png differ diff --git a/meowth/launcher.py b/meowth/launcher.py index 3cf877e5f..f65ed8819 100644 --- a/meowth/launcher.py +++ b/meowth/launcher.py @@ -147,7 +147,7 @@ def main(): pass # when not restarting, show exit code and exit fully - print("Exit code: {exit_code}".format(exit_code=code)) + print(f"Exit code: {code}") sys.exit(code) if __name__ == '__main__': diff --git a/requirements.txt b/requirements.txt index 62dfd43dd..b0cb6512f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,8 @@ aiocontextvars==0.2.2 aiohttp==3.7.4.post0 async-timeout==3.0.1 -asyncpg==0.25.0 +asyncpg==0.28.0 attrs==21.4.0 -backports.zoneinfo==0.2.1 certifi==2021.10.8 chardet==4.0.0 charset-normalizer==2.0.12 @@ -14,16 +13,14 @@ fuzzywuzzy==0.18.0 googlemaps==4.6.0 idna==3.3 imageio==2.16.1 --e git+https://github.com/FoglyOgly/Meowth.git@25af28ea97c6abca9d3d6996c0c1cdef55984643#egg=Meowth more-itertools==8.12.0 multidict==6.0.2 numpy==1.22.3 Pillow==9.0.1 -pkg_resources==0.0.0 psutil==5.9.0 python-dateutil==2.8.2 -python-Levenshtein==0.12.2 -pytz==2021.3 +python-Levenshtein==0.23.0 +pytz==2023.3 pytz-deprecation-shim==0.1.0.post0 regex==2022.3.2 requests==2.27.1 @@ -31,7 +28,7 @@ six==1.16.0 staticmap==0.5.5 timezonefinder==5.2.0 typing_extensions==4.1.1 -tzdata==2021.5 +tzdata==2023.3 tzlocal==4.1 urllib3==1.26.8 yarl==1.7.2 diff --git a/setup.py b/setup.py index b6b9277fc..f8398d06f 100644 --- a/setup.py +++ b/setup.py @@ -10,14 +10,14 @@ setup( name='Meowth', - version='3.0.0b', + version='3.0.0', author='FoglyOgly, Scragly', url='https://github.com/FoglyOgly/Meowth', license='GPLv3', description='A Discord Bot for Pokemon Go Communities.', long_description=readme, include_package_data=True, - + packages=['meowth'], install_requires=requirements, # this will be dead next month with the new pip version