async def list_accounts(ctx): try: guild_id = ctx.message.guild.id accounts_str = '' c.execute('select screen_name, channel_id from database where guild_id = (?)', (guild_id, )) accounts = c.fetchall() #Check that the list is not empty if len(accounts) != 0: embed_var = discord.Embed(title=f'Account list for {ctx.message.guild.name}', color=0x0) accounts_str = '' channel_name_str = '' channel_id_str = '' for account in accounts: accounts_str += f'- {account[0]}\n' channel_name_str += f'{client.get_channel(account[1])}\n' channel_id_str += f'{account[1]}\n' embed_var.add_field(name='Account', value=accounts_str, inline=True) embed_var.add_field(name='Channel name', value=channel_name_str, inline=True) embed_var.add_field(name='Channel ID', value=channel_id_str, inline=True) await ctx.send(embed=embed_var) else: await ctx.send(f'Nothing registered for {ctx.message.guild.name}') except Exception as e: logger.exception(e) print('GUILD : ' + ctx.message.guild.name + ' - ERROR : ' + str(e)) error_str = 'Error!\n `Code : {}`'.format(str(e)) await ctx.send(error_str)
async def help(ctx): try: embed_var = discord.Embed(title='Commands', description='Use the prefix \'!fetch \' to access the bot, followed by any of these commands.\n**WARNING**: removing the bot from your server will erase all of your Fetch settings from the database.', color=0x0) embed_var.add_field(name='info', value='General bot statistics and info.', inline=False) embed_var.add_field(name='add `<screen_name>` `<channel_id>`', value='Add a twitter account to the database, requires twitter handle (exclude @). `<channel_id>` is optional, if none specified current channel will be used. Use this command to update channel ID.', inline=False) embed_var.add_field(name='remove `<screen_name>`', value='Remove the user (and channel) from the database.', inline=False) embed_var.add_field(name='get-channel `<screen_name>`', value='Returns ID and name of the channel for this user.', inline=False) embed_var.add_field(name='list', value='List all twitter accounts that the bot looks out for in this server.', inline=False) embed_var.add_field(name='help', value='The command you\'re seeing right now.', inline=False) await ctx.send(embed=embed_var) except Exception as e: logger.exception(e) print('GUILD : ' + ctx.message.guild.name + ' - ERROR : ' + str(e)) error_str = 'Error!\n `Code : {}`'.format(str(e)) await ctx.send(error_str)
async def get_channel(ctx, screen_name): try: guild_id = ctx.message.guild.id c.execute('select channel_id from database where guild_id = (?) and screen_name = (?)', (guild_id, screen_name)) row = c.fetchone() if row is not None: #Channel (and user) exist, post name and ID await ctx.send(f'Channel ID: `{row[0]}`\nChannel name: {client.get_channel(row[0])}') else: #Channel (and user) not found await ctx.send('Channel was not found for this user in the database.') except Exception as e: logger.exception(e) print('GUILD : ' + ctx.message.guild.name + ' - ERROR : ' + str(e)) error_str = 'Error!\n `Code : {}`'.format(str(e)) await ctx.send(error_str)
async def add_account(ctx, screen_name, channel_id = None): try: if channel_id == None: channel_id = ctx.message.channel.id guild_id = ctx.message.guild.id channel_id = int(channel_id) #Check if the channel exists before doing anything else if client.get_channel(channel_id) is None: await ctx.send('Channel does not exist.') return #Make sure the account has no @ if screen_name.startswith('@'): await ctx.send('Type the account name without the @.') return user = api.get_user(screen_name) c.execute('select * from database where screen_name = (?) and guild_id = (?)', (screen_name, guild_id)) row = c.fetchone() if row is None: #User was not found in the database for the server c.execute('insert into database values (?,?,0,?)', (guild_id, screen_name, channel_id)) await ctx.send(f'User {user.screen_name} has been added to {ctx.message.guild.name}.\nChannel: `{channel_id}`') else: #User was found, check if channel_id is the same c.execute('select channel_id from database where screen_name = (?) and guild_id = (?)', (screen_name, guild_id)) row = c.fetchone() if row[0] == channel_id: #Channel_id is the same, no need to change it await ctx.send('User and channel are already registered.') else: #Channel_id is different, update it c.execute('update database set channel_id = (?) where guild_id = (?) and screen_name = (?)', (channel_id, guild_id, screen_name)) await ctx.send(f'Channel was updated for user {user.screen_name}') conn.commit() except Exception as e: logger.exception(e) print('GUILD : ' + ctx.message.guild.name + ' - ERROR : ' + str(e)) error_str = 'Error!\n `Code : {}`'.format(str(e)) await ctx.send(error_str)
async def remove_account(ctx, screen_name): try: guild_id = ctx.message.guild.id #Look if the user is in the database for the server c.execute('select * from database where screen_name = (?) and guild_id = (?)', (screen_name, guild_id)) row = c.fetchone() if row is not None: #User exists, remove it c.execute('delete from database where screen_name = (?) and guild_id = (?)', (screen_name, guild_id)) await ctx.send(f'User {screen_name} has been removed from the database for {ctx.message.guild.name}') else: #User is not in the database await ctx.send(f'User {screen_name} was not found in the database.') conn.commit() except Exception as e: logger.exception(e) print('GUILD : ' + ctx.message.guild.name + ' - ERROR : ' + str(e)) error_str = 'Error!\n `Code : {}`'.format(str(e)) await ctx.send(error_str)
async def update_fetch(): #Remove unneeded guilds before starting remove_guilds() #Get updated guild list guilds = get_guilds() for guild in guilds: accounts, channels = get_accounts_and_channels(guild) for account, channel_id in zip (accounts, channels): try: channel = client.get_channel(channel_id) #Check that the channel still exists if channel is not None: #Tries to find both self replies and original tweet with replies ON tweet = api.user_timeline(account, count = 1, tweet_mode = "extended", exclude_replies = False, include_rts = False)[0] if (tweet.in_reply_to_screen_name == tweet.user.screen_name or tweet.in_reply_to_screen_name == None) == False: #If the last tweet is a reply to another user, rollback to last original tweet tweet = api.user_timeline(account, count = 1, tweet_mode = "extended", exclude_replies = True, include_rts = False)[0] if tweet: tweet_timestamp = (tweet.created_at - datetime.datetime(1970,1,1)).total_seconds() tweet_link = f"https://twitter.com/{tweet.user.screen_name}/status/{tweet.id}" old_timestamp = get_timestamp(guild, account) #Check that tweet is actually new if tweet_timestamp - old_timestamp > 0: update_timestamp(guild, account, tweet_timestamp) #Post only if it's not older than 5 minutes if (tweet_timestamp - ((datetime.datetime.utcnow() - datetime.datetime(1970,1,1)).total_seconds() - 5*60)) > 0: await channel.send(tweet_link) else: print('Test') else: print('ERROR: Channel not found!') #In case added account has no tweets except IndexError as e: #logger.exception(e) #print('GUILD : ' + client.get_guild(guild).name + ' - ERROR : ' + str(e)) #error_str = 'Error!\nUser {} has no tweets!\nRemoving user...'.format(account) #await channel.send(error_str) #remove_account(guild, account) continue #In case rate limit in exceeded except tweepy.RateLimitError as e: logger.exception(e) print('GUILD : ' + client.get_guild(guild).name + ' - ERROR : ' + str(e)) error_str = 'Error!\nTwitter Rate Limit exceeded!' await channel.send(error_str) #Generic Twitter error except tweepy.TweepError as e: logger.exception(e) print('GUILD : ' + client.get_guild(guild).name + ' - ERROR : ' + str(e)) error_str = 'Error!\n `Code : {}`'.format(str(e)) #await channel.send(error_str) continue
import logging import sys from setup import logger from PyQt5 import QtWidgets from app.main_window import MainWindow from db import db if __name__ == "__main__": logger.setLevel(logging.DEBUG) logger.info('App start') app = QtWidgets.QApplication(sys.argv) main_window = None try: db.connect() db.create_tables([]) # fixme main_window = MainWindow(app) main_window.show() sys.exit(app.exec()) except Exception as e: logger.exception(e) finally: db.close() # todo check if main_window: main_window.stop() logger.info('App close')