Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import discord, asyncio, aiohttp, json, time, datetime, pickle, os.path, re, traceback, COC, sys, time, random
- from discord.ext import commands, tasks
- from googleapiclient.discovery import build
- from google_auth_oauthlib.flow import InstalledAppFlow
- from google.auth.transport.requests import Request
- from motor.motor_asyncio import AsyncIOMotorClient
- from sshtunnel import SSHTunnelForwarder
- from tinydb import TinyDB, Query, where
- from concurrent.futures import ThreadPoolExecutor
- import logging
- logger = logging.getLogger('discord')
- logger.setLevel(logging.ERROR)
- handler = logging.FileHandler(filename='discord.log', encoding='utf-8', mode='w')
- handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
- logger.addHandler(handler)
- home_coc_token = """REDACTED"""
- test_bot_token = 'REDACTED'
- clan_DB = TinyDB('clan_database.json')
- waitlist_DB = TinyDB('waitlist_database.json')
- bot_DB = TinyDB('bot_database.json')
- client = AsyncIOMotorClient()
- plyr_DB = client.player_database
- url = "https://api.clashofclans.com/v1/"
- params = None
- headers = {
- 'Accept': "application/json",
- 'Authorization': "Bearer " + home_coc_token
- }
- SCOPES = ['REDACTED']
- def time_to_sync(): #returns number of seconds until sync start
- #REDACTED INFORMATION
- # Call the Calendar API
- #FWA ID: REDACTED
- now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
- try:
- record = bot_DB.search(where('server_id') == 321963490111913987)
- test_ch = record[0]['test_ch_id']
- calendar_id = record[0]['calendar_id']
- events_result = service.events().list(calendarId=calendar_id, timeMin=now, #change ID in this line
- maxResults=10, singleEvents=True,
- orderBy='startTime').execute()
- events = events_result.get('items', [])
- if not events:
- print(f'Sync has not posted. Time: {datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S")}')
- return False
- #time stamps come in format: 2019-11-25T08:00:00-08:00
- sync_start = datetime.datetime.strptime(events[0]['start']['dateTime'], '%Y-%m-%dT%H:%M:%S%z')
- curr_time = datetime.datetime.strptime(str(time.strftime('%Y-%m-%dT%H:%M:%S%z')), '%Y-%m-%dT%H:%M:%S%z')
- dt = sync_start - curr_time
- return int(dt.total_seconds())
- except KeyError:
- return False
- except:
- logger.exception("Fatal error in time_to_sync")
- print(traceback.format_exc())
- return False
- class FWA_EvoCog(commands.Cog,name="FWA_Evo"):
- def __init__(self, bot):
- self.bot = bot
- self.check_routine.start()
- async def cog_check(self, ctx):
- return ctx.message.guild == 321963490111913987
- async def set_past_war_stats(self, clantag, data): # clan is in war
- resp = data
- record = clan_DB.search(where('clantag')==resp['clan']['tag'])
- if record[0]['past_war']['startTime'] != resp['startTime']: #if start times are different, overwrite
- members_in_war = []
- for member in range(len(resp['clan']['members'])):
- members_in_war.append(resp['clan']['members'][member]['tag'][1:])
- record = {'startTime': resp['startTime'],
- 'endTime': resp['endTime'],
- 'members': members_in_war}
- clan = Query()
- clan_DB.update({'past_war': record}, clan.clantag == f'#{clantag}')
- else: #if start times are the same, clan is still in war and notify members to use attacks
- end_time = datetime.datetime.strptime(str(resp['endTime']), "%Y%m%dT%H%M%S.%fZ")
- curr_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- curr_time = datetime.datetime.strptime(curr_time, "%Y-%m-%d %H:%M:%S")
- dt = end_time - curr_time
- deltat = int(dt.total_seconds())
- if deltat < 3600: #tag roles in channels to use their attacks
- record = clan_DB.search(where('clan_stats')['name'] == resp['name'])
- channel = self.bot.get_channel(record[0]['clan_stats']['channel'])
- server = self.bot.get_guild(321963490111913987)
- role = server.get_role(record[0]["clan_stats"]["role"])
- await channel.send(f'{role.mention} there is less than 2 hours of war left. Use your attacks now for maximum loot!')
- else: pass #otherwise do nothing
- async def set_current_war_stats(self, clantag, data): # clan is in prep day
- resp = data
- record = clan_DB.search(where('clantag')==resp['clan']['tag'])
- if record[0]['current_war']['startTime'] != resp['startTime']: #if start times are different, overwrite
- members_in_war = []
- for member in range(len(resp['clan']['members'])):
- members_in_war.append(resp['clan']['members'][member]['tag'][1:])
- record = {'startTime': resp['startTime'],
- 'endTime': resp['endTime'],
- 'members': members_in_war}
- clan = Query()
- clan_DB.update({'current_war': record, 'clan_notification': False}, clan.clantag == f'#{clantag}')
- else: pass
- async def members_not_in_clan(self, clantag): #returns list of members who are not in clan that are in current war
- record = clan_DB.search(where('clantag') == clantag)
- members_in_war = record[0]["current_war"]["members"]
- members_in_clan = []
- resp = await COC.Clan(clantag).clan_members
- for member in range(len(resp)):
- members_in_clan.append(resp[member])
- return list(set(members_in_war) - set(members_in_clan))
- async def tag_missing_members(self, clanname, clantag, channel): #tags missing members from war before sync
- members_list = await self.members_not_in_clan(clantag)
- if members_list == [] or members_list == None: print(f'No member to tag for {clanname}')
- else:
- member_id_list = []
- for index in range(len(members_list)):
- account = await COC.wizbot(members_list[index]).get_id
- if account:
- member_id_list.append(int(account))
- else: pass
- for index in range(len(member_id_list)):
- await channel.send(f'<@{member_id_list[index]}>, sync is coming up soon. Get back to {clanname} ASAP!')
- def cog_unload(self):
- self.check_routine.cancel()
- @tasks.loop(seconds=3600)
- async def check_routine(self):
- await self.bot.wait_until_ready()
- record = bot_DB.search(where('server_id') == 321963490111913987)
- test_ch = self.bot.get_channel(record[0]['test_ch_id'])
- loop = asyncio.get_event_loop()
- time_left = await loop.run_in_executor(None, time_to_sync)
- threshold = random.randint(6000,9000)
- for clan in clan_DB:
- try:
- status = await COC.Clan(clan['clantag'][1:]).clan_war_status
- if status['state'] == 'notInWar' or status['state']== 'warEnded':
- await test_ch.send(f'{clan["name"]} is not in war. Time: {datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S")}')
- channel = self.bot.get_channel(clan['channel'])
- server = self.bot.get_guild(321963490111913987)
- role = server.get_role(clan['role'])
- if time_left != False and time_left <= threshold and time_left >= 0: await self.tag_missing_members(clan['name'], clan['tag'], channel)
- if time_left <= 39600 and not clan['clan_notification']:
- await channel.send(f'{role.mention}, sync time has been posted. Be back in clan no more than **10** hours from now!!')
- clan_DB.update({'clan_notification': True}, where('clantag') == f'#{clan}')
- elif status['state'] == 'preparation':
- await test_ch.send(f'{clan["name"]} is in prep. Time: {datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S")}')
- await self.set_current_war_stats(clan, status)
- elif status['state'] == 'inWar':
- await test_ch.send(f'{clan["name"]} is in war. Time: {datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S")}')
- channel = self.bot.get_channel(clan['channel'])
- server = self.bot.get_guild(321963490111913987)
- role = server.get_role(clan['role'])
- await self.set_past_war_stats(clan, status)
- if time_left != False and time_left <= threshold and time_left >= 0:
- await channel.send(f'Tagging members in {clan["name"]}. Time: {datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S")}')
- await self.tag_missing_members(clan['name'], clan['tag'], test_ch)
- if time_left != False and time_left <= 39600 and time_left >= 0 and not clan['clan_notification']:
- await channel.send(f'{role.mention}, sync time has been posted. Be back in clan no more than **10** hours from now!!')
- clan_DB.update({'clan_notification': True}, where('clantag') == f'#{clan}')
- else: print('Error')
- except Exception:
- await test_ch.send(f'<@{148319665188372481}>, Unexpected error with routine at {datetime.datetime.now().strftime("%H:%M:%S")}. Check log for details.')
- logger.exception("Fatal error in main loop")
- print(traceback.format_exc())
- def setup(bot):
- bot.add_cog(FWA_EvoCog(bot))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement