3221 Commits

Author SHA1 Message Date
Chris Miles
a0a28fef04
[Strings] Add exception handling to converters themselves (#3029) 2023-03-04 19:39:55 -06:00
nytmyr
65c14b160e
[Rules] Add ResurrectionEffectsBlock (#2990)
* [Rules] Add ResurrectionEffectsBlock

Notes:

This adds the rule Spells:ResurrectionEffectsBlock that will prevent anything from overwrites Resurrection Sickness Effects. Currently they are able to be overwritten by certain spells.

Default state: Disabled/False.

* Update ruletypes.h

---------

Co-authored-by: Chris Miles <akkadius1@gmail.com>
2023-03-04 17:24:29 -06:00
Alex King
c21d47f450
[Scaling] Add support for pipe-separated zone IDs and versions (#3015)
* [Scaling] Add support for pipe-separated zone IDs and versions

# Notes
- Allows `|` separated zone IDs and instance versions within the scaling data.
- Loads scaling data on zone bootup as well, without needing to repop for it to initialize.

* Cleanup
2023-03-04 17:24:16 -06:00
Aeadoin
83ea9816b8
[Rules] Add Multiplier for Heroic Stats. (#3014)
* initial work

* [Rules] Add Multiplier for Heroic Stats.

* Add bots

* update SendStatsWindow

* fix SendStatsWindow
2023-03-04 17:09:44 -06:00
Chris Miles
e3f9b396ab
[Console] Add IS_TTY to force terminal coloring output (#3021) 2023-03-04 17:01:39 -06:00
Alex King
2a6cf8c8e7
[Strings] Add more number formatters (#2873)
* [Strings] Add more number formatters

# Notes
- Adds `Strings::ToUnsignedInt` for `uint32` support.
- Adds `Strings::ToBigInt` for `int64` support.
- Adds `Strings::ToUnsignedBigInt` for `uint64` support.
- Adds `Strings::ToFloat` for `float` support.
- Replaces all `std::stoi` references with `Strings::ToInt`.
- Replaces all `atoi` references with `Strings::ToInt`.
- Replaces all `std::stoul` references with `Strings::ToUnsignedInt`.
- Replaces all `atoul` references with `Strings::ToUnsignedInt`.
- Replaces all `std::stoll` references with `Strings::ToBigInt`.
- Replaces all `atoll` references with `Strings::ToBigInt`.
- Replaces all `std::stoull` references with `Strings::ToUnsignedBigInt`.
- Replaces all `atoull` references with `Strings::ToUnsignedBigInt`.
- Replaces all `std::stof` references with `Strings::ToFloat`.

* [Strings] Add more number formatters

- Adds `Strings::ToUnsignedInt` for `uint32` support.
- Adds `Strings::ToBigInt` for `int64` support.
- Adds `Strings::ToUnsignedBigInt` for `uint64` support.
- Adds `Strings::ToFloat` for `float` support.
- Replaces all `std::stoi` references with `Strings::ToInt`.
- Replaces all `atoi` references with `Strings::ToInt`.
- Replaces all `std::stoul` references with `Strings::ToUnsignedInt`.
- Replaces all `atoul` references with `Strings::ToUnsignedInt`.
- Replaces all `std::stoll` references with `Strings::ToBigInt`.
- Replaces all `atoll` references with `Strings::ToBigInt`.
- Replaces all `std::stoull` references with `Strings::ToUnsignedBigInt`.
- Replaces all `atoull` references with `Strings::ToUnsignedBigInt`.
- Replaces all `std::stof` references with `Strings::ToFloat`.

* Rebase cleanup

* Changes/benchmarks/tests

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-03-04 17:01:19 -06:00
cybernine186
be567af70d
[Bug Fix] Cursor Coin Upon Death (#3020)
* Update corpse.cpp

* Add rule toggle.

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2023-03-04 17:45:42 -05:00
Chris Miles
d3ca636a70
[Release] 22.4.5 (#3022) 2023-03-03 17:09:39 -06:00
Chris Miles
5f68e4a41a
[Release] 24.4.4 (#2989) 2023-02-24 20:51:45 -06:00
Alex King
2a20c69c69
[Scaling] Add support for zone ID and instance version to NPC Scaling (#2968)
* [Scaling] Add support for zone ID and instance version to NPC Scaling

# Notes
- Adds `zone_id` and `instance_version` to `npc_scale_global_base` table to allow for zone and version-specific scaling.
- Defaults back to `zone_id` of `0` and `instance_version` of `0` for global scaling.
- Scaling load precedence is as follows:
- `zone_id` of current zone and `instance_version` of current instance
- `zone_id` of current zone and `instance_version` of `0`
- `zone_id` of `0` and `instance_version` of `0`

* Remove debug comment.

* Use zone not NPC.

* SQL
2023-02-24 20:17:07 -06:00
Alex
de2dfc1a7e
[Bug Fix] Fix for undefined MySQL library behavior. (#2834)
* MYSQL objects cannot be copied in a well defined way, this removes the copy and replaces it with another connection

* Change to share underlying pointers.

* Push up mutex changes

* Post rebase

* Formatting

---------

Co-authored-by: KimLS <KimLS@peqtgc.com>
Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-02-24 20:14:55 -06:00
Chris Miles
bad631df59
[Player Events] Add QS processing, mutex tweaks (#2984)
* [Player Events] Add QS processing, mutex tweaks

* Update ucs.cpp

* Move the size process check out of the server to server networking thread
2023-02-24 18:01:59 -06:00
Chris Miles
e8f1aa253a
[Pathing] Smoother pathing z-correction (#2982) 2023-02-24 14:07:44 -06:00
nytmyr
2ae0b7dd3e
[Bug Fix] Correct Mend reuse time and add reduction support. (#2972)
Notes:

Previously, the server-side reuse of Mend was set to 290 seconds rather than 360 seconds (6 minutes).

Mend was not accepting reduction timers from potential items, buffs or AAs (Hastened Mend).

Mend was outputting duplicate success messages on critical mends, it will now only output a regular Mend message upon success (You mend your wounds and heal some damage) or the critical message upon critical success (You magically mend your wounds and heal considerable damage), not both.

Co-authored-by: toxin06 <53322305+toxin06@users.noreply.github.com>
2023-02-23 02:39:45 -06:00
Aeadoin
afaa8f4100
[Bots] Add Caster Range Command, and IsValidSpellRange Checks (#2942)
* [Bots] Add Caster Range Command, and IsValidSpellRange Checks

* remove/add exceptions where makes sense like buffs

* fixes

* fixes
2023-02-23 02:36:17 -06:00
Chris Miles
fcb0a47280
[Release] 22.4.3 (#2976) 2023-02-21 10:42:43 -06:00
Chris Miles
33bb5aa8e5
[Database] Address deadlock in player events (#2974)
* DB mutex testing

* Mutex tweaks, native string escaping
2023-02-20 22:32:29 -06:00
Chris Miles
9f42da5bad
[Crash] Fix world crash in player event processing (#2960)
* [Crash] Fix world crash in player event processing

* Add rule BatchPlayerEventProcessChunkSize
2023-02-18 16:06:16 -06:00
Chris Miles
db4c515853
[Player Events] Create new event ITEM_CREATION (#2944) 2023-02-18 16:05:23 -06:00
Chris Miles
4ad3ebf36a
[Release] 22.4.2 (#2957) 2023-02-18 10:18:32 -06:00
Chris Miles
b5a2713a3a
[Player Events] Add logging category to hold processing batch logs (#2954)
* [Player Events] Add logging category to hold processing batch logs

* Update player_event_logs.cpp
2023-02-18 05:41:14 -06:00
Chris Miles
da20a6ab67
[Player Events] Fix rare out of bound issue when loading event types (#2946) 2023-02-17 06:06:53 -06:00
Chris Miles
3949a31246
[Fix] Issue with AssignRaidToInstance that was using the groups repository instead of raid (#2947) 2023-02-17 06:06:45 -06:00
Chris Miles
e898be1ce9
[Player Events] Turn off KILLED_NPC (trash) off by default (#2948) 2023-02-17 06:05:43 -06:00
Akkadius
2962575dda [Hotfix] Missing comma in schema list breaking dumps 2023-02-16 22:27:09 -06:00
Chris Miles
df69d12c0c
[Release] 22.4.0 (#2940)
* [Release] 22.4.0

* Update changelog notes [skip ci]
2023-02-16 10:23:01 -06:00
Chris Miles
536e248424
[Windows] Fix MSVC compilation bug via workaround (#2926) 2023-02-13 21:21:05 -06:00
Alex King
97edb09fba
[Rules] Add Group/Raid Experience Rules (#2850)
# Notes
- Add `Character:EnableGroupMemberEXPModifier`, enables or disables member-based experience modifiers in groups, default `true`.
- Add `Character:EnableRaidEXPModifier`, enables or disables member-based experience modifiers in raids, default `true`.
- Add `Character:EnableRaidMemberEXPModifier`, enables or disables member-based experience modifiers in raids, default `true`.
2023-02-13 00:25:59 -06:00
Chris Miles
d9f545a5ec
[Logging] Implement Player Event Logging system (#2833)
* Plumbing

* Batch processing in world

* Cleanup

* Cleanup

* Update player_event_logs.cpp

* Add player zoning event

* Use generics

* Comments

* Add events

* Add more events

* AA_GAIN, AA_PURCHASE, FORAGE_SUCCESS, FORAGE_FAILURE

* FISH_SUCCESS, FISH_FAILURE, ITEM_DESTROY

* Add charges to ITEM_DESTROY

* WENT_ONLINE, WENT_OFFLINE

* LEVEL_GAIN, LEVEL_LOSS

* LOOT_ITEM

* MERCHANT_PURCHASE

* MERCHANT_SELL

* SKILL_UP

* Add events

* Add more events

* TASK_ACCEPT, TASK_COMPLETE, and TASK_UPDATE

* GROUNDSPAWN_PICKUP

* SAY

* REZ_ACCEPTED

* COMBINE_FAILURE and COMBINE_SUCCESS

* DROPPED_ITEM

* DEATH

* SPLIT_MONEY

* TRADER_PURCHASE and TRADER_SELL

* DISCOVER_ITEM

* Convert GM_COMMAND to use new macro

* Convert ZONING event to use macro

* Revert some code changes

* Revert "Revert some code changes"

This reverts commit d53682f997e89a053a660761085913245db91e9d.

* Add cereal generation support to repositories

* TRADE

* Formatting

* Cleanup

* Relocate discord_manager to discord folder

* Discord sending plumbing

* Rename UCS's Database class to UCSDatabase to be more specific and not collide with base Database class for repository usage

* More discord sending plumbing

* More discord message formatting work

* More discord formatting work

* Discord formatting of events

* Format WENT_ONLINE, WENT_OFFLINE

* Add merchant purchase event

* Handle Discord MERCHANT_SELL formatter

* Update player_event_discord_formatter.cpp

* Tweaks

* Implement retention truncation

* Put mutex locking on batch queue, put processor on its own thread

* Process on initial bootup

* Implement optional QS processing, implement keepalive from world to QS

* Reload player event settings when logs are reloaded in game

* Set settings defaults

* Update player_event_logs.cpp

* Update player_event_logs.cpp

* Set retention days on boot

* Update player_event_logs.cpp

* Player Handin Event Testing.

Testing player handin stuff.

* Cleanup.

* Finish NPC Handin.

* set a reference to the client inside of the trade object as well for plugins to process

* Fix for windows _inline

* Bump to cpp20 default, ignore excessive warnings on windows

* Bump FMT to 6.1.2 for cpp20 compat and swap fmt::join for Strings::Join

* Windows compile fixes

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CMakeLists.txt

* Create 2022_12_19_player_events_tables.sql

* [Formatters] Work on Discord Formatters

* Handin money.

* Format header

* [Formatters] Work on Discord Formatters

* Format

* Format

* [Formatters] More Formatter work, need to test further.

* [Formatters] More Work on Formatters.

* Add missing #endif

* [Formatters] Work on Formatters, fix Bot formatting in ^create help

* NPC Handin Discord Formatter

* Update player_event_logs.cpp

* Discover Item Discord Formatter

* Dropped Item Discord Formatter

* Split Money Discord Formatter

* Trader Discord Formatters

* Cleanup.

* Trade Event Discord Formatter Groundwork

* SAY don't record GM commands

* GM_Command don't record #help

* Update player_event_logs.cpp

* Fill in more event data

* Post rebase fixes

* Post rebase fix

* Discord formatting adjustments

* Add event deprecation or unimplemented tag support

* Trade events

* Add return money and sanity checks.

* Update schema

* Update ucs.cpp

* Update client.cpp

* Update 2022_12_19_player_events_tables.sql

* Implement archive single line

* Replace hackers table and functions with PossibleHack player event

* Replace very old eventlog table since the same events are covered by player event logs

* Update bot_command.cpp

* Record NPC kill events ALL / Named / Raid

* Add BatchEventProcessIntervalSeconds rule

* Naming

* Update CMakeLists.txt

* Update database_schema.h

* Remove logging function and methods

* DB version

* Cleanup SendPlayerHandinEvent

---------

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
Co-authored-by: Aeadoin <109764533+Aeadoin@users.noreply.github.com>
2023-02-12 21:31:01 -06:00
Alex King
268879b414
[Quest API] Add Recipe-based methods to Perl/Lua. (#2844)
* [Quest API] Add Recipe-based methods to Perl/Lua.

# Perl
- Add `quest::get_recipe_component_item_ids(recipe_id)`.
- Add `quest::get_recipe_container_item_ids(recipe_id)`.
- Add `quest::get_recipe_fail_item_ids(recipe_id)`.
- Add `quest::get_recipe_salvage_item_ids(recipe_id)`.
- Add `quest::get_recipe_success_item_ids(recipe_id)`.
- Add `quest::get_recipe_component_count(recipe_id, item_id)`.
- Add `quest::get_recipe_fail_count(recipe_id, item_id)`.
- Add `quest::get_recipe_salvage_count(recipe_id, item_id)`.
- Add `quest::get_recipe_success_count(recipe_id, item_id)`.

# Lua
- Add `eq.get_recipe_component_item_ids(recipe_id)`.
- Add `eq.get_recipe_container_item_ids(recipe_id)`.
- Add `eq.get_recipe_fail_item_ids(recipe_id)`.
- Add `eq.get_recipe_salvage_item_ids(recipe_id)`.
- Add `eq.get_recipe_success_item_ids(recipe_id)`.
- Add `eq.get_recipe_component_count(recipe_id, item_id)`.
- Add `eq.get_recipe_fail_count(recipe_id, item_id)`.
- Add `eq.get_recipe_salvage_count(recipe_id, item_id)`.
- Add `eq.get_recipe_success_count(recipe_id, item_id)`.

# Notes
- Before these methods, you would have to use DBI from Perl or Lua in order to get the components and their counts, these methods allow easy access to these values via the scripting API.
- These should be used sparingly as they're each an individual database hit and could go crazy in a hot path.

* Update eq_constants.h

* Update zonedb.h

* Update tradeskills.cpp

* Reserve.
2023-02-07 21:42:34 -05:00
Chris Miles
158396937a
[Release] 22.3.0 (#2842)
* [Release] 22.3.0

* Update version.h

* Redirect stderr

* Update should-release to filter non-master

* Update should-release
2023-02-06 20:12:04 -06:00
Chris Miles
0a114fae9a
[Doors] Have NPCs trigger double doors (#2821) 2023-02-06 17:47:03 -06:00
Chris Miles
2b224d42ad
[Rules] Fix rule updates that affected bot booting checks (#2841) 2023-02-06 17:31:50 -06:00
Natedog2012
155ec9ac0d
[Quest API] Add rule AlternateAugmentationSealer for using a different bagtype (#2831)
* [Quest API] Add rule AlternateAugmentationSealer for using a different bagtype as an alternate augmentation sealer. Use EVENT_COMBINE with UseAugmentContainer

* Default it to be off or bagtype 53 (BagTypeAugmentationSealer)
2023-02-06 17:30:16 -06:00
Joel
839f31b24d
[Rule] Added rule to bypass level based haste caps (#2835) 2023-02-06 17:25:17 -06:00
Chris Miles
d369b47ef4
[Tasks] Implement alternate currency rewards (#2827)
* Reward currency on task completion

* Handle reward window

* Tweaks
2023-02-06 17:24:13 -06:00
Chris Miles
404f7cada8
[Pathing] Improvements to handling tight corridors pathing, clipping detection and recovery (#2826) 2023-02-06 17:24:03 -06:00
Chris Miles
0da6391be3
[Doors] Remove door dev tools spam on client controlled doors (#2824)
* [Doors] Remove door dev tools spam on client controlled doors

* Update client_packet.cpp

* Update client_packet.cpp

* Update ruletypes.h
2023-02-06 17:23:40 -06:00
Vayle
b385a4385f
[Rules] Add rule to ignore name filter on chat channel creation. (#2820)
* [Rules] Add rule to ignore name filter on chat channel creation.

* Conditional reorder
2023-02-06 17:22:12 -06:00
Chris Miles
6a9228ed6e
[Lua] Resolve stoi Exception (#2736)
* [Lua] Resolve stoi Exception

* Change fallback for wp, not really needed for safety

* Change to Strings::ToInt
2023-02-06 17:22:01 -06:00
Alex King
040c092795
[Quest API] Add Augment Slot support to does_augment_fit (#2813)
* [Quest API] Add Augment Slot support to does_augment_fit

# Notes
- Allows you to check if the supplied augment ID fits in the specified augment slot of the item instance provided.

* Update item_instance.cpp
2023-01-30 21:18:16 -05:00
Alex King
0fef46a6c1
[Feature] Add Min/Max Status to Merchants (#2806)
# Notes
- Allows operators to set a minimum and maximum status that an item will show for players.
- Allows operators to have items on a merchant that only a GM can see.
- Some servers may use status for different things, so having a minimum and a maximum will allow for more functionality.
- Default of `min_status` is `0` (Player) and default of `max_status` is `255` (Max).
2023-01-29 15:03:41 -05:00
Alex King
549d731849
[Bug Fix] Resolve issue with max buff count being 25 in ROF2. (#2800)
# Notes
- This allows ROF2 to properly utilize their max buff count.
- May cause issues with older clients.
2023-01-28 17:40:11 -06:00
Akkadius
cb2aee2713 [Release] 22.2.0 2023-01-27 01:12:30 -06:00
Natedog2012
1fe79f430c
[Feature] ResetItemCooldown added to lua/perl and fix item re-cast times to show properly (#2793)
* Testing.

* Add ResetItemCooldown and port it over to perl

* This flag needs to be set for updating shared item cooldowns

* Properly set item recast for all item types, on corpses, on looting

* SummonItem properly sets recast timers of summoned items

* Rename variable to avoid confusion and change manifest to be more specific

* Sanity check item_d

* Recast -1 added as RECAST_TYPE_UNLINKED_ITEM
ResetItemCooldown will still remove cooldown of item that we don't have so when we acquire it the cooldown is reset

* change magic numbers

* more magic numbers

* More constants yay

* Remove unneeded export DeleteItemRecastTimer

* Remove duplicate message, this is handled by the client in this part of the code

Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
2023-01-25 20:09:08 -06:00
Alex King
5720ffbcb6
[Release] 22.1.2 (#2791) 2023-01-24 17:18:42 -06:00
Chris Miles
08c8393988
[CI/CD] Build / Release Pipeline Changes (#2788)
* Test

* Test

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* Kill excessive warnings

* Split

* Remove 7z from build scripts

* Linux

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Test

* Update .drone.yml

* Naming

* Test upload

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Yolo

* Yolo

* Update .drone.yml

* Update .drone.yml

* Copy

* Yolo

* Release without bots

* Update .drone.yml

* Update .drone.yml

* Test pipeline

* Remove debug

* Update .drone.yml

* Filter pipeline stage

* Update .drone.yml

* Test

* Bots release 22.0.5 (Test)

* Release bot test #2

* Check if release

* Update .drone.yml

* Update .drone.yml

* exit 78

* Update .drone.yml

* Update .drone.yml

* Add version checks

* Update .drone.yml

* Update .drone.yml

* Test

* Update build-release.bat

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update build-release.bat

* Update build-release.bat

* Test pipeline

* Update CHANGELOG.md

* Bump

* Update build-release.bat

* Update build-release.bat

* Shuffle

* Take #45354

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* F

* Update windows-build.ps1

* Consolidate

* Run it

* Pop cache back in

* Update linux-build.sh

* Another release test

* Update linux-build.sh

* Update linux-build.sh

* Update CMakeLists.txt

* Trim windows assets

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* [22.1.0] Release

* Crash reporting

* Add version tag injection in the build pipeline

* Update windows-build.ps1

* Test

* Test

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* Kill excessive warnings

* Split

* Remove 7z from build scripts

* Linux

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Test

* Update .drone.yml

* Naming

* Test upload

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Yolo

* Yolo

* Update .drone.yml

* Update .drone.yml

* Copy

* Yolo

* Release without bots

* Update .drone.yml

* Update .drone.yml

* Test pipeline

* Remove debug

* Update .drone.yml

* Filter pipeline stage

* Update .drone.yml

* Test

* Bots release 22.0.5 (Test)

* Release bot test #2

* Check if release

* Update .drone.yml

* Update .drone.yml

* exit 78

* Update .drone.yml

* Update .drone.yml

* Add version checks

* Update .drone.yml

* Update .drone.yml

* Test

* Update build-release.bat

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update build-release.bat

* Update build-release.bat

* Test pipeline

* Update CHANGELOG.md

* Bump

* Update build-release.bat

* Update build-release.bat

* Shuffle

* Take #45354

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* F

* Update windows-build.ps1

* Consolidate

* Run it

* Pop cache back in

* Update linux-build.sh

* Another release test

* Update linux-build.sh

* Update linux-build.sh

* Update CMakeLists.txt

* Trim windows assets

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* Update windows-build.ps1

* [22.1.0] Release

* Crash reporting

* Add version tag injection in the build pipeline

* Update windows-build.ps1

* Full crash report on windows.

* Update endpoint

* [22.1.1] Release

* [skip ci] update .drone.yml

* Filter

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update .drone.yml

* Update CHANGELOG.md

Co-authored-by: KimLS <KimLS@peqtgc.com>
2023-01-24 16:37:04 -06:00
Chris Miles
037be84f38
[Crash] Fix rarer world crash issue where scheduler database was not available (#2789) 2023-01-24 12:38:26 -06:00
Aeadoin
293f79268d
[Bots] Fix Slow Query in QueryNameAvailablity (#2781) 2023-01-22 18:26:57 -05:00
Alex King
3335cacac1
[Bots] Cleanup and remove preprocessors. (#2757)
* [Bots] Cleanup and remove preprocessors.

- Removes every `#ifdef BOTS` we have and locks bots behind `Bots:AllowBots` rule.
- Bot updates are now done by default similar to regular database updates.
- Modify `CMakeLists.txt`, `.drone.yml`, and `BUILD.md` to match the removal of `EQEMU_ENABLE_BOTS`.

* Cleanup

- Add SQL for enabling bots for servers with bots.
- Add message that tells players/operators bots are disabled.

* Suggested changes.

* Bot injection stuff

* Change SQL to bot SQL.

* Tweaks

* Remove `is_bot`

* Update version.h

* Update main.cpp

* Update database.cpp

* Fix name availability crash

* Remove bots from update script

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-01-20 12:35:33 -06:00