Skip to content
This repository has been archived by the owner on Jan 15, 2024. It is now read-only.

Commit

Permalink
Merge branch 'release/2022.30.2' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
TurnrDev committed Jul 30, 2022
2 parents 3e504e0 + 556e216 commit 0161f7b
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 395 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

## [2021.30.1] - 2022-07-30
### Changed
- We have OCR again! `/update image:` to use it

## [2021.30.1] - 2022-07-25
### Changed
- Fix leaderboards not loading if a server has no icon
Expand Down Expand Up @@ -178,7 +182,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- `[p]progress (mention)`
- Settings commands

[Unreleased]: https://github.com/TrainerDex/ DiscordBot/compare/v2022.30.0...develop
[Unreleased]: https://github.com/TrainerDex/ DiscordBot/compare/v2022.30.2...develop
[2022.30.0]: https://github.com/TrainerDex/DiscordBot/compare/v2022.30.1...v2022.30.2
[2022.30.0]: https://github.com/TrainerDex/DiscordBot/compare/v2022.30.0...v2022.30.1
[2022.30.0]: https://github.com/TrainerDex/DiscordBot/compare/v2021.43.0...v2022.30.0
[2021.43.0]: https://github.com/TrainerDex/DiscordBot/compare/v2020.48.0...v2021.43.0
[2020.48.0]: https://github.com/TrainerDex/DiscordBot/compare/v2020.40.2...v2020.48.0
Expand Down
1 change: 0 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ name = "pypi"
humanize = "*"
python-dateutil = "*"
trainerdex = "==3.7"
PogoOCR = "==0.4.0b2"
py-cord = ">=2.0.0"
aiostream = "*"
motor = ">=3.0,<3.1"
Expand Down
353 changes: 5 additions & 348 deletions Pipfile.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[![Support Server](https://img.shields.io/discord/364313717720219651.svg?color=7289da&label=TrainerDex&logo=discord&style=flat)](https://discord.gg/bDPnJ2)
[![Translation status](https://hosted.weblate.org/widgets/trainerdex/-/discord-bot/svg-badge.svg)](https://hosted.weblate.org/engage/trainerdex/)
[![Maintenance](https://img.shields.io/static/v1?label=Maintained?&message=bug+fixes+only&color=orange&style=flat)](#)
[![Maintenance](https://img.shields.io/static/v1?label=Maintained?&message=Yes!&color=green&style=flat)](#)
[![wakatime](https://wakatime.com/badge/github/TrainerDex/DiscordBot.svg?style=flat)](https://wakatime.com/badge/github/TrainerDex/DiscordBot)
[![Visit our Sponsor](https://img.shields.io/static/v1?label=Sponsored+by&message=Wynaut+Wyandotte&color=7289da&logo=discord&style=flat)](https://discord.gg/jJKVAPw4Pw)
[![Sponsor us](https://img.shields.io/static/v1?label=Patreon&message=TrainerDexApp&color=ff424d&style=flat)](https://www.patreon.com/TrainerDexApp)
Expand Down
22 changes: 19 additions & 3 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,25 @@
This section will be updated when the bot goes public, very soon.

## Configuring the bot
Generally, you will need `Manage Server` or `Administrator` permissions to use any of the config commands on the bot. These permissions were picked to match the permissions Discord requires to install the bot.

### Setting up the mod roles
First things first, you will want to set which roles the bot should consider a mod. This has two halves to it. The bot, and Discord. First we will configure Discord.

#### Discord Config
1) Go to the [Integrations](https://user-images.githubusercontent.com/11667059/181601459-d14db6d5-c756-4a47-8448-c34d3d2c988e.png)
tab within your Server Settings.
2) Scroll down and select the TrainerDex integration. This is where you can control who can see and trigger commands within the Discord UI.
3) Select `/approve` and tap the No ❎ option for `@everyone`. Add a role override for the role(s) you assign your mods and slect the green check mark ✔️. ([Example](https://user-images.githubusercontent.com/11667059/181602221-29e17512-4cc8-4019-84bc-599700a97324.png))
4) Rince and repeat for `/server-config`.

Now we've told Discord to show these commands to the mod roles. By default, it will only show to users with **Administrator** or **Manage Server** permissions otherwise.

#### Bot Config
Unfortunately, Discord has been known to screw up and just show the command to everybody anyway. So I was forced to add in some validation in the actual command. So we're going to have to set that up too:
- Run the following command: `/server-config mod-roles action: Add role role: x` for each of your mod role(s) ([Example](https://user-images.githubusercontent.com/11667059/181603960-9317fb4b-8688-47fc-8fba-8582171d7c8c.png))
- If you don't run this command, the bot will most likely ignore calls to priviledged commands (`/approve` and `/server-config`)

## Command list

The following commands exist:
- `/server-config mod-roles` - Provides functionality to set which roles on your server are considered mods. The bot will consider somebody a mod if they have `Manage Server`, `Administrator` permissions, or one of the roles in this list.
Expand All @@ -21,8 +39,6 @@ The following commands exist:

- `/server-config tl40-role` - Set a role you use to restrict level 40+ players. Currently not used as the levels system is being reworked.

<!-- - `/server-config introduction_note` - this is unused -->

- `/approve` - the command to grant a user access to your server, and creates a TrainerDex profile for them. This takes several params, including team, username and Total XP.
- Notes on Username: You **must** set this to their In-Game Trainer Name. Please ensure `i` is `i`, `L` is `L` etc, although we understand these can get mixed up. When in doubt, ask the user what it is.
- Notes on Total XP: This is the trainers all time Total XP, **not** the XP progress through their current level.
Expand Down
2 changes: 1 addition & 1 deletion trainerdex_discord_bot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
"""

VERSION = (2022, 30, 1, "final", 0)
VERSION = (2022, 30, 2, "final", 0)

__version__ = f"{VERSION[0]}.{VERSION[1]}.{VERSION[2]}-{VERSION[3]}.{VERSION[4]}"
9 changes: 8 additions & 1 deletion trainerdex_discord_bot/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,14 @@ async def on_ready() -> None:
},
)
private_logger.info("Public: %(public)s", {"public": app_info.bot_public})
logger.info("Bot loaded at {time}.".format(time=datetime.datetime.utcnow().isoformat()))
logger.info(
"Bot loaded at {time}.".format(
time=chat_formatting.format_time(
datetime.datetime.now(),
chat_formatting.TimeVerbosity.LONG_DATETIME,
)
)
)

@bot.event
async def on_application_command_error(ctx: ApplicationContext, exception: Exception) -> None:
Expand Down
53 changes: 14 additions & 39 deletions trainerdex_discord_bot/cogs/post.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import datetime
from decimal import Decimal
from typing import TYPE_CHECKING, Optional
from typing import TYPE_CHECKING, Dict, Optional

from discord import (
ApplicationContext,
Expand All @@ -11,54 +11,36 @@
slash_command,
)
from discord.utils import snowflake_time
from google.oauth2 import service_account
from PogoOCR import OCRClient, Screenshot, ScreenshotClass
from PogoOCR.providers import Providers

from trainerdex_discord_bot.cogs.interface import Cog
from trainerdex_discord_bot.config import TokenDocuments
from trainerdex_discord_bot.constants import STAT_MAP
from trainerdex_discord_bot.embeds import ProfileCard
from trainerdex_discord_bot.new_ocr_client import NewOCRClient
from trainerdex_discord_bot.utils import chat_formatting
from trainerdex_discord_bot.utils.converters import get_trainer, get_trainer_from_user
from trainerdex_discord_bot.utils.general import send
from trainerdex_discord_bot.utils.validators import validate_trainer_nickname

if TYPE_CHECKING:
from PogoOCR.images.actitvity_view import ActivityViewData
from trainerdex.trainer import Trainer
from trainerdex.update import Update


class PostCog(Cog):
async def __post_init__(self) -> None:
await super().__post_init__()

self.ocr = None
if google_token := await self.config.get_token(TokenDocuments.GOOGLE.value):
credentials: service_account.Credentials = (
service_account.Credentials.from_service_account_info(google_token)
)
self.ocr = OCRClient(credentials=credentials, provider=Providers.GOOGLE)

@property
def ocr_initialized(self) -> bool:
return isinstance(self.ocr, OCRClient)

@slash_command(
name="update",
description="Update your stats with an image, optionally a few other stats are included.",
options=[
Option(int, name="total_xp", description="Total XP", required=False),
Option(int, name="pokestops_visited", description="Backpacker", required=False),
Option(int, name="capture_total", description="Collector", required=False),
Option(float, name="travel_km", description="Jogger", required=False),
Option(
Attachment,
name="image",
description="Image for OCR, when it's working again.",
description="Image for OCR",
required=False,
),
Option(int, name="total_xp", description="Total XP", required=False),
Option(int, name="pokestops_visited", description="Backpacker", required=False),
Option(int, name="capture_total", description="Collector", required=False),
Option(float, name="travel_km", description="Jogger", required=False),
Option(int, name="gym_gold", description="Gold Gym Badges", required=False),
Option(int, name="unique_pokestops", description="Sightseer", required=False),
Option(int, name="legendary_battle_won", description="Battle Legend", required=False),
Expand All @@ -84,11 +66,11 @@ def ocr_initialized(self) -> bool:
async def update_via_slash_command(
self,
ctx: ApplicationContext,
image: Attachment | None = None,
total_xp: int | None = None,
pokestops_visited: int | None = None,
capture_total: int | None = None,
travel_km: float | None = None,
image: Attachment | None = None,
gym_gold: int | None = None,
unique_pokestops: int | None = None,
legendary_battle_won: int | None = None,
Expand Down Expand Up @@ -166,16 +148,9 @@ async def update_via_slash_command(
return

data_from_ocr = {}
if self.ocr_initialized and image is not None:
if image is not None:
try:
screenshot = await Screenshot.from_url(
image.url,
klass=ScreenshotClass.ACTIVITY_VIEW,
asyncronous=True,
)

request = self.ocr.open_request(screenshot)
result: ActivityViewData = self.ocr.process_ocr(request)
result: Dict[str, float] = await NewOCRClient.request_activitiy_view_scan(image)
except Exception:
if not kwargs:
await send(
Expand All @@ -194,10 +169,10 @@ async def update_via_slash_command(
)
else:
data_from_ocr: dict[str, Decimal | int | None] = {
"travel_km": result.travel_km,
"capture_total": result.capture_total,
"pokestops_visited": result.pokestops_visited,
"total_xp": result.total_xp,
"travel_km": result.get("Distance"),
"capture_total": result.get("Pokémon"),
"pokestops_visited": result.get("PokéStops"),
"total_xp": result.get("Total"),
}

stats_to_update = kwargs | data_from_ocr
Expand Down
20 changes: 20 additions & 0 deletions trainerdex_discord_bot/new_ocr_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import os
from typing import ClassVar, Dict

import aiohttp
from discord import Attachment


class NewOCRClient:

HOST: ClassVar[str] = os.environ.get("TRAINERDEX_HOST", "https://trainerdex.app")

@classmethod
async def request_activitiy_view_scan(cls, image: Attachment) -> Dict[str, float]:
async with aiohttp.ClientSession() as session:
headers = {
"Content-Disposition": f"attachment; filename={image.filename}"
}
async with session.put(f'{cls.HOST}/api/ocr/activity-view/', data=await image.read(), headers=headers) as resp:
resp.raise_for_status()
return await resp.json()
18 changes: 18 additions & 0 deletions trainerdex_discord_bot/utils/chat_formatting.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import calendar
from datetime import datetime
from enum import Enum
import textwrap
from decimal import ROUND_HALF_UP, Decimal
from io import BytesIO
Expand Down Expand Up @@ -430,3 +433,18 @@ def format_numbers(number: int | float | Decimal, ndigits: int = 2) -> str:
if not float(number).is_integer():
number = Decimal(number).quantize(Decimal(f"0.{'0' * ndigits}"), rounding=ROUND_HALF_UP)
return humanize.intcomma(number)

class TimeVerbosity(Enum):
"""Enum for the verbosity of the :func:`format_time` function."""
SHORT_DATE = "d"
LONG_DATE = "D"
SHORT_TIME = "t"
LONG_TIME = "T"
SHORT_DATETIME = "f"
LONG_DATETIME = "F"
DELTA = "R"


def format_time(dt: datetime, verbosity: TimeVerbosity = TimeVerbosity.LONG_DATETIME) -> str:
"""Formats a datetime in a way Discord loves it"""
return f"<t:{calendar.timegm(dt.utctimetuple())}:{verbosity.value}>"

0 comments on commit 0161f7b

Please sign in to comment.