Merge pull request #20 from ShootingKing-AM/feature-topgg
New module Topgg
This commit is contained in:
@@ -7,6 +7,7 @@ from .stats import *
|
||||
from .user_config import *
|
||||
from .workout import *
|
||||
from .todo import *
|
||||
from .topgg import *
|
||||
from .reminders import *
|
||||
from .renting import *
|
||||
from .moderation import *
|
||||
|
||||
@@ -60,7 +60,7 @@ async def cmd_send(ctx):
|
||||
return await ctx.embed_reply("We are still waiting for {} to open an account.".format(target.mention))
|
||||
|
||||
# Finally, send the amount and the ack message
|
||||
target_lion.addCoins(amount)
|
||||
target_lion.addCoins(amount, ignorebonus=True)
|
||||
source_lion.addCoins(-amount)
|
||||
|
||||
embed = discord.Embed(
|
||||
|
||||
@@ -61,10 +61,10 @@ async def cmd_set(ctx):
|
||||
# Postgres `coins` column is `integer`, sanity check postgres int limits - which are smalled than python int range
|
||||
target_coins_to_set = target_lion.coins + amount
|
||||
if target_coins_to_set >= 0 and target_coins_to_set <= POSTGRES_INT_MAX:
|
||||
target_lion.addCoins(amount)
|
||||
target_lion.addCoins(amount, ignorebonus=True)
|
||||
elif target_coins_to_set < 0:
|
||||
target_coins_to_set = -target_lion.coins # Coins cannot go -ve, cap to 0
|
||||
target_lion.addCoins(target_coins_to_set)
|
||||
target_lion.addCoins(target_coins_to_set, ignorebonus=True)
|
||||
target_coins_to_set = 0
|
||||
else:
|
||||
return await ctx.embed_reply("Member coins cannot be more than {}".format(POSTGRES_INT_MAX))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import asyncio
|
||||
from codecs import ignore_errors
|
||||
import logging
|
||||
import traceback
|
||||
import datetime
|
||||
@@ -500,7 +501,7 @@ class ReactionRoleMessage:
|
||||
if price and refund:
|
||||
# Give the user the refund
|
||||
lion = Lion.fetch(self.guild.id, member.id)
|
||||
lion.addCoins(price)
|
||||
lion.addCoins(price, ignorebonus=True)
|
||||
|
||||
# Notify the user
|
||||
embed = discord.Embed(
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from data import RowTable
|
||||
from data.interfaces import RowTable
|
||||
|
||||
|
||||
reminders = RowTable(
|
||||
'reminders',
|
||||
('reminderid', 'userid', 'remind_at', 'content', 'message_link', 'interval', 'created_at'),
|
||||
('reminderid', 'userid', 'remind_at', 'content', 'message_link', 'interval', 'created_at', 'title', 'footer'),
|
||||
'reminderid'
|
||||
)
|
||||
|
||||
@@ -150,12 +150,14 @@ class Reminder:
|
||||
|
||||
# Build the message embed
|
||||
embed = discord.Embed(
|
||||
title="You asked me to remind you!",
|
||||
title="You asked me to remind you!" if self.data.title is None else self.data.title,
|
||||
colour=discord.Colour.orange(),
|
||||
description=self.data.content,
|
||||
timestamp=datetime.datetime.utcnow()
|
||||
)
|
||||
embed.add_field(name="Context?", value="[Click here]({})".format(self.data.message_link))
|
||||
|
||||
if self.data.message_link:
|
||||
embed.add_field(name="Context?", value="[Click here]({})".format(self.data.message_link))
|
||||
|
||||
if self.data.interval:
|
||||
embed.add_field(
|
||||
@@ -165,6 +167,9 @@ class Reminder:
|
||||
)
|
||||
)
|
||||
|
||||
if self.data.footer:
|
||||
embed.set_footer(text=self.data.footer)
|
||||
|
||||
# Update the reminder data, and reschedule if required
|
||||
if self.data.interval:
|
||||
next_time = self.data.remind_at + datetime.timedelta(seconds=self.data.interval)
|
||||
|
||||
6
bot/modules/topgg/__init__.py
Normal file
6
bot/modules/topgg/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from .module import module
|
||||
|
||||
from . import webhook
|
||||
from . import commands
|
||||
from . import data
|
||||
from . import settings
|
||||
76
bot/modules/topgg/commands.py
Normal file
76
bot/modules/topgg/commands.py
Normal file
@@ -0,0 +1,76 @@
|
||||
import discord
|
||||
from .module import module
|
||||
from wards import guild_admin
|
||||
from bot.cmdClient.checks.global_perms import in_guild
|
||||
from settings.user_settings import UserSettings
|
||||
|
||||
from .webhook import on_dbl_vote
|
||||
from .utils import *
|
||||
|
||||
@module.cmd(
|
||||
"forcevote",
|
||||
desc="Simulate Topgg Vote.",
|
||||
group="Guild Admin",
|
||||
aliases=('debugvote', 'topggvote')
|
||||
)
|
||||
@guild_admin()
|
||||
async def cmd_forcevote(ctx):
|
||||
"""
|
||||
Usage``:
|
||||
{prefix}forcevote
|
||||
Description:
|
||||
Simulate Topgg Vote without actually a confirmation from Topgg site.
|
||||
|
||||
Can be used for force a vote for testing or if topgg has an error or production time bot error.
|
||||
"""
|
||||
target = ctx.author
|
||||
# Identify the target
|
||||
if ctx.args:
|
||||
if not ctx.msg.mentions:
|
||||
return await ctx.error_reply("Please mention a user to simulate a vote!")
|
||||
target = ctx.msg.mentions[0]
|
||||
|
||||
await on_dbl_vote({"user": target.id, "type": "test"})
|
||||
return await ctx.reply('Topgg vote simulation successful on {}'.format(target))
|
||||
|
||||
|
||||
@module.cmd(
|
||||
"vote",
|
||||
desc="Get top.gg boost for 25% more LCs.",
|
||||
group="Economy",
|
||||
aliases=('topgg', 'topggvote', 'upvote')
|
||||
)
|
||||
@in_guild()
|
||||
async def cmd_vote(ctx):
|
||||
"""
|
||||
Usage``:
|
||||
{prefix}vote
|
||||
Description:
|
||||
Get Top.gg bot's link for +25% Economy boost.
|
||||
"""
|
||||
target = ctx.author
|
||||
|
||||
embed=discord.Embed(
|
||||
title="Claim your boost!",
|
||||
description='Please click [here](https://top.gg/bot/889078613817831495/vote) vote and support our bot!\n\nThank you! {}.'.format(lion_loveemote),
|
||||
colour=discord.Colour.orange()
|
||||
).set_thumbnail(
|
||||
url="https://cdn.discordapp.com/attachments/908283085999706153/933012309532614666/lion-love.png"
|
||||
)
|
||||
return await ctx.reply(embed=embed)
|
||||
|
||||
|
||||
@module.cmd(
|
||||
"vote_reminder",
|
||||
group="Personal Settings",
|
||||
desc="Turn on/off boost reminders."
|
||||
)
|
||||
async def cmd_remind_vote(ctx):
|
||||
"""
|
||||
Usage:
|
||||
`{prefix}vote_reminder on`
|
||||
`{prefix}vote_reminder off`
|
||||
|
||||
Enable or disable DM boost reminders.
|
||||
"""
|
||||
await UserSettings.settings.vote_remainder.command(ctx, ctx.author.id)
|
||||
8
bot/modules/topgg/data.py
Normal file
8
bot/modules/topgg/data.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from data.interfaces import RowTable
|
||||
|
||||
topggvotes = RowTable(
|
||||
'topgg',
|
||||
('voteid', 'userid', 'boostedTimestamp'),
|
||||
'voteid'
|
||||
)
|
||||
|
||||
68
bot/modules/topgg/module.py
Normal file
68
bot/modules/topgg/module.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from multiprocessing import context
|
||||
from LionModule import LionModule
|
||||
from LionContext import register_reply_callback, unregister_reply_callback
|
||||
from bot.data.conditions import NOT
|
||||
from meta.client import client
|
||||
from core.lion import register_addcoins_callback, unregister_addcoins_callback
|
||||
|
||||
from .utils import *
|
||||
from .webhook import init_webhook
|
||||
|
||||
module = LionModule("Topgg")
|
||||
|
||||
upvote_info = "You have a boost available {}, to support our project and earn **25% more LionCoins** type `{}vote` {}"
|
||||
|
||||
@module.launch_task
|
||||
async def register_hook(client):
|
||||
init_webhook()
|
||||
register_reply_callback(reply)
|
||||
register_addcoins_callback(cb_addCoins)
|
||||
|
||||
client.log("Registered LionContext reply util hook.", context="Topgg" )
|
||||
|
||||
@module.unload_task
|
||||
async def unregister_hook(client):
|
||||
unregister_reply_callback(reply)
|
||||
unregister_addcoins_callback(cb_addCoins)
|
||||
|
||||
client.log("Unregistered LionContext reply util hook.", context="Topgg" )
|
||||
|
||||
|
||||
def reply(util_func, *args, **kwargs):
|
||||
# *args will have LionContext
|
||||
# **kwargs should have the actual reply() call's extra arguments
|
||||
|
||||
if not get_last_voted_timestamp(args[0].author.id):
|
||||
args = list(args)
|
||||
|
||||
upvote_info_formatted = upvote_info.format(lion_yayemote, args[0].best_prefix, lion_loveemote)
|
||||
|
||||
if 'embed' in kwargs:
|
||||
kwargs['embed'].add_field(
|
||||
name="\u200b",
|
||||
value=(
|
||||
upvote_info_formatted
|
||||
),
|
||||
inline=False
|
||||
)
|
||||
elif 'content' in args and args['content']:
|
||||
args['content'] += '\n\n' + upvote_info_formatted
|
||||
elif len(args) > 1:
|
||||
args[1] += '\n\n' + upvote_info_formatted
|
||||
else:
|
||||
args['content'] = '\n\n' + upvote_info_formatted
|
||||
|
||||
args = tuple(args)
|
||||
|
||||
return [args, kwargs]
|
||||
|
||||
|
||||
def cb_addCoins(self, amount, flush, ignorebonus):
|
||||
|
||||
client.log('cb_addCoins hook with amount={} ignorebonux={}'.format(amount, ignorebonus), context='Topgg')
|
||||
|
||||
if not ignorebonus and amount > 0 and get_last_voted_timestamp(self.userid):
|
||||
amount *= 1.25
|
||||
client.log('cb_addCoins with bonus={}'.format(amount), context='Topgg')
|
||||
|
||||
return [self, amount, flush, ignorebonus]
|
||||
45
bot/modules/topgg/settings.py
Normal file
45
bot/modules/topgg/settings.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from settings.user_settings import UserSettings, UserSetting
|
||||
from settings.setting_types import Boolean
|
||||
|
||||
from modules.reminders.reminder import Reminder
|
||||
from modules.reminders.data import reminders
|
||||
|
||||
from .utils import *
|
||||
|
||||
@UserSettings.attach_setting
|
||||
class topgg_vote_remainder(Boolean, UserSetting):
|
||||
attr_name = 'vote_remainder'
|
||||
_data_column = 'remaind_upvote'
|
||||
|
||||
_default = True
|
||||
|
||||
display_name = 'Upvote Reminder'
|
||||
desc = "Turn on/off DM Reminders to Upvote me."
|
||||
long_desc = ("Enable or disable DM boost reminders.",)
|
||||
|
||||
@property
|
||||
def success_response(self):
|
||||
if self.value:
|
||||
# Check if reminder is already running
|
||||
create_remainder(self.id)
|
||||
|
||||
return (
|
||||
" I will send you boost reminders.\n\n"
|
||||
"`Please make sure your DMs are open.`"
|
||||
)
|
||||
else:
|
||||
# Check if reminder is already running and get its id
|
||||
r = reminders.select_one_where(
|
||||
userid=self.id,
|
||||
select_columns='reminderid',
|
||||
content=remainder_content,
|
||||
_extra="ORDER BY remind_at DESC LIMIT 1"
|
||||
)
|
||||
|
||||
# Cancel and delete Remainder if already running
|
||||
if r:
|
||||
Reminder.delete(r['reminderid'])
|
||||
|
||||
return (
|
||||
" I won't send you boost reminders."
|
||||
)
|
||||
79
bot/modules/topgg/utils.py
Normal file
79
bot/modules/topgg/utils.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from email.mime import image
|
||||
import discord
|
||||
import datetime
|
||||
from meta.client import client
|
||||
from bot.settings.setting_types import Integer
|
||||
from meta import sharding
|
||||
|
||||
from modules.reminders.reminder import Reminder
|
||||
from modules.reminders.data import reminders
|
||||
|
||||
from . import data as db
|
||||
from data.conditions import GEQ
|
||||
|
||||
topgg_upvote_link = 'https://top.gg/bot/889078613817831495/vote'
|
||||
remainder_content = "You can now vote again on top.gg!\nClick [here]({}) to vote, thank you for the support!".format(topgg_upvote_link)
|
||||
|
||||
lion_loveemote = '<:lionloveemote:933003977656795136>'
|
||||
lion_yayemote = '<:lionyayemote:933003929229352990>'
|
||||
|
||||
# Will return None if user has not voted in [-12.5hrs till now]
|
||||
# else will return a Tuple containing timestamp of when exactly she voted
|
||||
def get_last_voted_timestamp(userid: Integer):
|
||||
return db.topggvotes.select_one_where(
|
||||
userid=userid,
|
||||
select_columns="boostedTimestamp",
|
||||
boostedTimestamp=GEQ(datetime.datetime.utcnow() - datetime.timedelta(hours=12.5)),
|
||||
_extra="ORDER BY boostedTimestamp DESC LIMIT 1"
|
||||
)
|
||||
|
||||
# Checks if a remainder is already running (immaterial of remind_at time)
|
||||
# If no remainder exists creates a new remainder and schedules it
|
||||
def create_remainder(userid):
|
||||
if not reminders.select_one_where(
|
||||
userid=userid,
|
||||
content=remainder_content,
|
||||
_extra="ORDER BY remind_at DESC LIMIT 1"
|
||||
):
|
||||
last_vote_time = get_last_voted_timestamp(userid)
|
||||
|
||||
# if no, Create reminder
|
||||
reminder = Reminder.create(
|
||||
userid=userid,
|
||||
# TODO using content as a selector is not a good method
|
||||
content=remainder_content,
|
||||
message_link=None,
|
||||
interval=None,
|
||||
title="Your boost is now available! {}".format(lion_yayemote),
|
||||
footer="Use `{}vote_reminder off` to stop receiving reminders.".format(client.prefix),
|
||||
remind_at=last_vote_time[0] + datetime.timedelta(hours=12.5) if last_vote_time else datetime.datetime.utcnow() + datetime.timedelta(minutes=5)
|
||||
# remind_at=datetime.datetime.utcnow() + datetime.timedelta(minutes=2)
|
||||
)
|
||||
|
||||
# Schedule reminder
|
||||
if sharding.shard_number == 0:
|
||||
reminder.schedule()
|
||||
|
||||
|
||||
async def send_user_dm(userid):
|
||||
# Send the message, if possible
|
||||
if not (user := client.get_user(userid)):
|
||||
try:
|
||||
user = await client.fetch_user(userid)
|
||||
except discord.HTTPException:
|
||||
pass
|
||||
if user:
|
||||
try:
|
||||
embed=discord.Embed(
|
||||
title="Thank you for supporting our bot on Top.gg! {}".format(lion_yayemote),
|
||||
description="By voting every 12 hours you will allow us to reach and help even more students all over the world.\n \
|
||||
Thank you for supporting us, enjoy your LionCoins boost!",
|
||||
colour=discord.Colour.orange()
|
||||
).set_image(
|
||||
url="https://cdn.discordapp.com/attachments/908283085999706153/932737228440993822/lion-yay.png"
|
||||
)
|
||||
|
||||
await user.send(embed=embed)
|
||||
except discord.HTTPException:
|
||||
# Nothing we can really do here. Maybe tell the user about their reminder next time?
|
||||
pass
|
||||
36
bot/modules/topgg/webhook.py
Normal file
36
bot/modules/topgg/webhook.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from meta.client import client
|
||||
from settings.user_settings import UserSettings
|
||||
from utils.lib import utc_now
|
||||
from meta.config import conf
|
||||
|
||||
import topgg
|
||||
from .utils import *
|
||||
|
||||
@client.event
|
||||
async def on_dbl_vote(data):
|
||||
"""An event that is called whenever someone votes for the bot on Top.gg."""
|
||||
client.log(f"Received a vote: \n{data}", context='Topgg')
|
||||
|
||||
db.topggvotes.insert(
|
||||
userid=data['user'],
|
||||
boostedTimestamp = utc_now()
|
||||
)
|
||||
|
||||
await send_user_dm(data['user'])
|
||||
|
||||
if UserSettings.settings.vote_remainder.value:
|
||||
create_remainder(data['user'])
|
||||
|
||||
if data["type"] == "test":
|
||||
return client.dispatch("dbl_test", data)
|
||||
|
||||
|
||||
@client.event
|
||||
async def on_dbl_test(data):
|
||||
"""An event that is called whenever someone tests the webhook system for your bot on Top.gg."""
|
||||
client.log(f"Received a test vote:\n{data}", context='Topgg')
|
||||
|
||||
|
||||
def init_webhook():
|
||||
client.topgg_webhook = topgg.WebhookManager(client).dbl_webhook(conf.bot.get("topgg_route"), conf.bot.get("topgg_password"))
|
||||
client.topgg_webhook.run(conf.bot.get("topgg_port"))
|
||||
Reference in New Issue
Block a user