Exemplo n.º 1
0
    def _get_imgur_secrets(self,
                           imgur_secrets: str) -> configparser.ConfigParser:
        """
        _get_imgur_secrets checks if the Imgur api secrets file exists.
        - If the file exists, this methods reads the the files and returns the secrets in as a dict.
        - If the file doesn't exist it asks the user over stdin to supply these values and then
          saves them into the imgur_secrets file

        Arguments:
            imgur_secrets (string): file name of secrets file for API credentials

        Returns:
            imgur_config (dict): Dictionary containing the client id and client secret needed to
            login to Imgur
        """

        if not os.path.exists(imgur_secrets):
            self.logger.warning(
                'Imgur API keys not found. (See wiki if you need help).')

            # Whitespaces are stripped from input: https://stackoverflow.com/a/3739939
            imgur_client_id = ''.join(
                input("[ .. ] Enter Imgur client ID: ").split())
            imgur_client_secret = ''.join(
                input("[ .. ] Enter Imgur client secret: ").split())
            # Make sure authentication is working
            try:
                imgur_client = ImgurClient(imgur_client_id,
                                           imgur_client_secret)

                # If this call doesn't work, it'll throw an ImgurClientError
                imgur_client.get_album('dqOyj')
                # It worked, so save the keys to a file
                imgur_config = configparser.ConfigParser()
                imgur_config['Imgur'] = {
                    'ClientID': imgur_client_id,
                    'ClientSecret': imgur_client_secret,
                }
                with open(imgur_secrets, 'w') as file:
                    imgur_config.write(file)
                file.close()
            except ImgurClientError as imgur_error:
                self.logger.error('Error while logging into Imgur: %s',
                                  imgur_error)
                self.logger.error(FATAL_TOOTBOT_ERROR)
                sys.exit(1)
        else:
            # Read API keys from secret file
            imgur_config = configparser.ConfigParser()
            imgur_config.read(imgur_secrets)

        return imgur_config
Exemplo n.º 2
0
def get_img(path):
    global pin
    client = ImgurClient(client_id, client_secret,'61c2a536adcd40eeedbd8e6fba18999f413bf5dc',
                         'aee3d76d7956080282f5d272f76ef12f19509a47')
##    if pin == None:
##        authorization_url = client.get_auth_url('pin')
##        print("Go to the following URL: {0}".format(authorization_url))
##        pin = input("Enter pin code: ")
##    else:
##        pass
##    credentials = client.authorize(pin, 'pin')
##    client.set_user_auth(credentials['access_token'], credentials['refresh_token'])
    # Example request
    album_id = '2hzdSFn'
    config = {
            'album': album_id,
            'name': 'test-name!',
            'title': 'test-title',
            'description': 'test-description'
            }
    print(client.get_album(album_id))
    client.upload_from_path(path,config=config,anon=False)
    images = client.get_album_images(album_id)
    url = images[len(images)-1].link
    return url
def main():
	parser = argparse.ArgumentParser(description="Generate BBCode from an Imgur album")
	parser.add_argument("-c", "--clientid", help="Imgur client ID", required=True)
	parser.add_argument("-s", "--secret", help="Imgur secret", required=True)
	parser.add_argument("-a", "--album", help="Album ID", required=True)

	args = parser.parse_args()

	client = ImgurClient(args.clientid, args.secret)

	try:
		album = client.get_album(args.album)
	except ImgurClientError as e:
		print "Error fetching album - %s:" % (e.status_code)
		print e.error_message
		exit()

	print '[B][SIZE="4"]%s[/SIZE][/B]' % (album.title)

	thumb_regex = re.compile(r"^(.*)\.(.{3,4})$")

	for img in album.images:
		if img['title']:
			print '[SIZE="3"]%s[/SIZE]\n' % (img['title'])
		# Use "large thumbnail" size
		print '[IMG]%s[/IMG]' % (thumb_regex.sub("\\g<1>l.\\2", img['link']))
		description = img['description'] if img['description'] else ""
		print description
		print
Exemplo n.º 4
0
def get_img():
    client_id = 'b9ae77105014a61'
    client_secret = '720fc83b0d748eb6131f987949280e15bf3a6e66'
    client = ImgurClient(client_id, client_secret)
    authorization_url = client.get_auth_url('pin')
    print("Go to the following URL: {0}".format(authorization_url))
    if os.path.isfile('pin.txt'):
        with open('pin.txt', 'r') as f:
            pin = f.read()
    else:
        pin = input("Enter pin code: ")
        with open('pin.txt', 'w') as f:
            f.write(pin)
    credentials = client.authorize(pin, 'pin')
    client.set_user_auth(credentials['access_token'],
                         credentials['refresh_token'])
    # Example request
    album_id = 'ARm1Dtq'
    config = {
        'album': album_id,
        'name': 'test-name!',
        'title': 'test-title',
        'description': 'test-description'
    }
    print(client.get_album('ARm1Dtq'))
    client.upload_from_path('D:/python/linebot/linebot/in.jpg',
                            config=config,
                            anon=False)
    images = client.get_album_images(album_id)
    url = images[len(images) - 1].link
    return url
Exemplo n.º 5
0
class API:
    def __init__(self, _client_id, _client_secret):
        self.client_id = _client_id
        self.client_secret = _client_secret
        self.client = ImgurClient(_client_id, _client_secret)
        pass

    def get_album_image_urls(self, _album_id):
        images = self.client.get_album(_album_id).__dict__['images']
        links = []
        for image in images:
            links.append(image['link'])
            pass
        return links
        pass

    def get_favorites_image_urls(self, username):
        images = self.client.get_account_favorites(username)
        links = []
        for image in images:
            links.append(image.__dict__['link'])
            pass
        return links
        pass

    pass
Exemplo n.º 6
0
def get_url(submission):
    def what_is_inside(url):
        header = requests.head(url).headers
        if 'Content-Type' in header:
            return header['Content-Type']
        else:
            return ''

    url = submission.url

    url_content = what_is_inside(url)
    if ('image/jpeg' == url_content or 'image/png' == url_content):
        return 'img', url, url_content.split('/')[1]

    if 'image/gif' in url_content:
        return 'gif', url, 'gif'

    if url.endswith('.gifv'):
        if 'image/gif' in what_is_inside(url[0:-1]):
            return 'gif', url[0:-1], 'gif'

    if submission.is_self is True:
        # Self submission with text
        return 'text', None, None

    if urlparse(url).netloc == 'imgur.com':
        # Imgur
        imgur_config = yaml.load(open('imgur.yml').read())
        imgur_client = ImgurClient(imgur_config['client_id'],
                                   imgur_config['client_secret'])
        path_parts = urlparse(url).path.split('/')
        if path_parts[1] == 'gallery':
            # TODO: gallary handling
            return 'other', url, None
        elif path_parts[1] == 'topic':
            # TODO: topic handling
            return 'other', url, None
        elif path_parts[1] == 'a':
            # An imgur album
            album = imgur_client.get_album(path_parts[2])
            story = {}
            for num, img in enumerate(album.images):
                number = num + 1
                story[number] = {
                    'link': img['link'],
                    'gif': img['animated'],
                    'type': img['type'].split('/')[1]
                }
            return 'album', story, None
        else:
            # Just imgur img
            img = imgur_client.get_image(path_parts[1].split('.')[0])
            if not img.animated:
                return 'img', img.link, img.type.split('/')[1]
            else:
                return 'gif', img.link, 'gif'

    else:
        return 'other', url, None
Exemplo n.º 7
0
def get_random_caturday_image():
    """Return url to random caturday image from album"""
    client = ImgurClient(
        CFG.get('imgur').get('clientid'),
        CFG.get('imgur').get('clientsecret')
    )
    album = client.get_album(CFG.get('imgur').get('caturdayalbum'))
    return choice([image.get('link') for image in album.images])
Exemplo n.º 8
0
async def caturday(ctx):
    """Show a random cat gif on caturdays"""
    ctx.channel.typing()
    client = ImgurClient(
        CFG.get('imgur').get('clientid'),
        CFG.get('imgur').get('clientsecret'))
    album = client.get_album(CFG.get('imgur').get('caturdayalbum'))
    image = choice([image.get('link') for image in album.images])
    await ctx.channel.send(image)
def venue():
    u = User.query.get(1)
    client = ImgurClient(
        current_app.config['IMGUR_CLIENT_ID'],
        current_app.config['IMGUR_CLIENT_SECRET'],
        access_token=u.access_token,
        refresh_token=u.refresh_token)
    album = client.get_album('izwJA')
    if client.auth.current_access_token != u.access_token:
        u.access_token = client.auth.current_access_token
        db.session.add(u)
        db.session.commit()
    return render_template('venue.html', album=album)
Exemplo n.º 10
0
def getImgurData(url):
    path = urllib.parse.urlparse(url).path
    path = str(path.split('/')[-1])
    logging.info(path)
    try:
        client = ImgurClient(config.imgur_client_id,
                             config.imgur_client_secret)
        items = client.get_album(path)
    except:
        logging.info("Bad Link Error")
        return 0, 0, 0
    #logging.info(items.title)
    #logging.info(items.images_count)
    #logging.info(items.images)
    return items.images_count, items.images, path
Exemplo n.º 11
0
def photos(album=None):
    if album is None:
        return redirect(url_for('public.photos', album='63Tp6'))
    u = User.query.get(1)
    client = ImgurClient(
        current_app.config['IMGUR_CLIENT_ID'],
        current_app.config['IMGUR_CLIENT_SECRET'],
        access_token=u.access_token,
        refresh_token=u.refresh_token)
    albums = client.get_account_albums('timandmikaela')
    for a in albums:
        if a.id == album:
            break
    else:
        abort(404)
    a = client.get_album(album)
    if client.auth.current_access_token != u.access_token:
        u.access_token = client.auth.current_access_token
        db.session.add(u)
        db.session.commit()
    return render_template('photos.html', album=a, albums=albums)
Exemplo n.º 12
0
def saveAlbum(album, author, sub, sub_title, direct):
    counter = 0
    client = ImgurClient(Im_client_id, Im_client_secret)  #Imgur client
    try:
        album_data = client.get_album(album)  #Whole album
        folderName = album_data.title  #album title

        if not folderName:
            folderName = sub_title + " - " + str(album)
            folderName = formatName(folderName)
        else:
            folderName = folderName.replace(' ', '_')
            folderName = formatName(folderName)
        print(album)
        images = client.get_album_images(album)
        print(album)

        for image in images:
            #print(str(image.link))
            #print(str(image.description))
            print(image.type)
            folder = direct + '/' + sub + '/' + author + '/' + str(
                folderName) + '/'
            #folder  = re.sub('[?/|\:<>*"]', '', folder)

            if not os.path.exists(folder):
                os.makedirs(folder)

            writeDescription(image.description, image.id, folder, counter)

            urllib.request.urlretrieve(
                image.link, folder + "(" + str(counter) + ") " +
                str(image.id) + str(image.type).replace('image/', '.'))

            counter = counter + 1
    except imgurpython.helpers.error.ImgurClientError:
        with open(direct + '/error.txt', 'a') as logFile:
            logFile.write('ImgurClientError: ' + album + '\n')
            logFile.close()
Exemplo n.º 13
0
def download_cubari_moe(url, chapters_asked, download_path, manga_name):
    if not os.path.exists(download_path + manga_name + os.path.sep):
        os.makedirs(download_path + manga_name + os.path.sep)
    download_path = download_path + manga_name + os.path.sep

    config = configparser.ConfigParser()
    config.read("mangas_dl/conf.ini")

    client = ImgurClient(config["IMGUR"]["ClientID"],
                         config["IMGUR"]["ClientSecret"])

    for chp_src, chp_nb in chapters_asked:
        sys.stdout.write('\033[K')
        print('Loading chapter ', chp_nb, end='\r')

        if not os.path.exists(download_path + 'temp' + os.path.sep):
            os.makedirs(download_path + 'temp' + os.path.sep)

        album = client.get_album(chp_src)
        srcs = [img["link"] for img in album.images]

        download_and_convert_to_pdf(srcs, download_path, chp_nb)
Exemplo n.º 14
0
def upload_photo(image_url, image_name):
	client_id = 'YOUR_CLIENT_ID'
	client_secret = 'YOUR_CLIENT_SECRET'
	access_token = 'YOUR_ACCESS_TOKEN'
	refresh_token = 'YOUR_REFRESH_TOKEN'
	client = ImgurClient(client_id, client_secret, access_token, refresh_token)
	album_id = 'YOUR_ALBUM_ID'
	album = client.get_album(album_id)
	# check whether image have been upload ever 
	for image in album.images:
		if image['name'] == image_name:
			print('Find image in Album {}!'.format(album_id))
			return image['link']

	# set configuration
	config = {
		'album': album_id,
		'name': image_name
	}
	print('Uploading image to imgur.com ... ...')
	image = client.upload_from_url(image_url, config=config, anon=False)
	print('Upload Done~')
	return image['link']
Exemplo n.º 15
0

import praw
from imgurpython import ImgurClient
from praw.models import Message
from praw.models import Comment
import random
import time
import sys

from _operator import contains
client_id = '*********'
client_secret = '*********'
client = ImgurClient(client_id, client_secret)
#items = client.gallery()
items = client.get_album('FlHzl')
#numPictures = items.__sizeof__()
reddit = praw.Reddit(client_id='*********',
                     client_secret="********", password='******',
                     user_agent='eyebleachbot (by /u/su5)', username='******')

messageBod = '''User: {0}

Subject: {1}


Body: {2}'''
response = '''NSFL? Yikes!

[Eye Bleach!](%s)
Exemplo n.º 16
0
    reddit_config.read('reddit.secret')
    REDDIT_AGENT = reddit_config['Reddit']['Agent']
    REDDIT_CLIENT_SECRET = reddit_config['Reddit']['ClientSecret']
# Setup and verify Imgur access
if not os.path.exists('imgur.secret'):
    print(
        '[WARN] API keys for Imgur not found. Please enter them below (see wiki if you need help).'
    )
    # Whitespaces are stripped from input: https://stackoverflow.com/a/3739939
    IMGUR_CLIENT = ''.join(input("[ .. ] Enter Imgur client ID: ").split())
    IMGUR_CLIENT_SECRET = ''.join(
        input("[ .. ] Enter Imgur client secret: ").split())
    # Make sure authentication is working
    try:
        imgur_client = ImgurClient(IMGUR_CLIENT, IMGUR_CLIENT_SECRET)
        test_gallery = imgur_client.get_album('dqOyj')
        # It worked, so save the keys to a file
        imgur_config = configparser.ConfigParser()
        imgur_config['Imgur'] = {
            'ClientID': IMGUR_CLIENT,
            'ClientSecret': IMGUR_CLIENT_SECRET
        }
        with open('imgur.secret', 'w') as f:
            imgur_config.write(f)
        f.close()
    except BaseException as e:
        print('[EROR] Error while logging into Imgur:', str(e))
        print('[EROR] Tootbot cannot continue, now shutting down')
        exit()
else:
    # Read API keys from secret file
Exemplo n.º 17
0
print '[*] imgur Album Downloader is now running'

# api stuff
client_id = '273e0cd6a27f629'
client_secret = '820135d39a35932f025b88b0a9d56b8bb6929096'
client = ImgurClient(client_id, client_secret)

# test link: http://imgur.com/a/pthXN
id = ''
while id == '':
	test = raw_input('[*] Please enter an imgur album link: ')
	if test == "exit":
		sys.exit()
	try:
		test_id = test[test.index('a/')+2:]
		album = client.get_album(test_id)
		id = test_id
	except Exception,e:
		print '[-] Error: Invalid imgur album link'

# test path: C:/Users/st/Documents/GitHub/Auto-Scripts/
dest = ''
while dest == '':
	tet_dest = raw_input('[*] Please enter a destination path: ')
	if os.path.exists(test_dest):
		dest = test_dest
	else:
		print '[-] Error: Invalid destination path'

print '[+] Downloading imgur album...'
images = client.get_album_images(id)
Exemplo n.º 18
0
def get_url(submission, mp4_instead_gif=True):
    '''
    return TYPE, URL
    E.x.: return 'img', 'http://example.com/pic.png'
    '''
    def what_is_inside(url):
        header = requests.head(url).headers
        if 'Content-Type' in header:
            return header['Content-Type']
        else:
            return ''

    # If reddit native gallery
    if hasattr(submission, 'gallery_data'):
        dict_of_dicts_of_pics = dict()
        list_of_media = dict()
        for item in submission.gallery_data['items']:
            list_of_media[item['id']] = item['media_id']
        counter = 0
        for item in sorted(list_of_media.items(), key=lambda item: item[0]):
            if counter % 10 == 0:
                dict_of_dicts_of_pics[counter // 10] = dict()
            item_with_media = submission.media_metadata[item[1]]['s']
            if 'u' in item_with_media:
                # It's a pic
                dict_of_dicts_of_pics[counter // 10][counter] = {
                    'url': item_with_media['u'],
                    'type': 'pic'
                }
            else:
                # It's a gif
                dict_of_dicts_of_pics[counter // 10][counter] = {
                    'url': item_with_media['mp4'],
                    'type': 'video'
                }
            counter += 1
        return TYPE_GALLERY, dict_of_dicts_of_pics

    url = submission.url
    url_content = what_is_inside(url)

    if submission.is_video:
        if 'reddit_video' in submission.media:
            if submission.media['reddit_video'].get('is_gif', False):
                return TYPE_GIF, submission.media['reddit_video'][
                    'fallback_url']
            return TYPE_VIDEO, submission.media['reddit_video']['fallback_url']
            # return TYPE_OTHER, url

    try:
        if len(submission.crosspost_parent_list) > 0:
            parent_submission_json = submission.crosspost_parent_list[0]
            if parent_submission_json['is_video'] == True:
                if 'reddit_video' in parent_submission_json['media']:
                    if parent_submission_json['media']['reddit_video'].get(
                            'is_gif', False):
                        return TYPE_GIF, parent_submission_json['media'][
                            'reddit_video']['fallback_url']
                    return TYPE_VIDEO, parent_submission_json['media'][
                        'reddit_video']['fallback_url']
    except:
        # Not a crosspost
        pass

    if (CONTENT_JPEG == url_content or CONTENT_PNG == url_content):
        return TYPE_IMG, url

    if CONTENT_GIF in url_content:
        if url.endswith('.gif') and mp4_instead_gif:
            # Let's try to find .mp4 file.
            url_mp4 = url[:-4] + '.mp4'
            if CONTENT_MP4 == what_is_inside(url_mp4):
                return TYPE_GIF, url_mp4
        return TYPE_GIF, url

    if url.endswith('.gifv'):
        if mp4_instead_gif:
            url_mp4 = url[:-5] + '.mp4'
            if CONTENT_MP4 == what_is_inside(url_mp4):
                return TYPE_GIF, url_mp4
        if CONTENT_GIF in what_is_inside(url[0:-1]):
            return TYPE_GIF, url[0:-1]

    if submission.is_self is True:
        # Self submission with text
        return TYPE_TEXT, None

    if urlparse(url).netloc == 'imgur.com':
        # Imgur
        imgur_config = yaml.safe_load(
            open(os.path.join('configs', 'imgur.yml')).read())
        imgur_client = ImgurClient(imgur_config['client_id'],
                                   imgur_config['client_secret'])
        path_parts = urlparse(url).path.split('/')
        if path_parts[1] == 'gallery':
            # TODO: gallary handling
            return TYPE_OTHER, url
        elif path_parts[1] == 'topic':
            # TODO: topic handling
            return TYPE_OTHER, url
        elif path_parts[1] == 'a':
            # An imgur album
            album = imgur_client.get_album(path_parts[2])
            story = dict()
            for num, img in enumerate(album.images):
                number = num + 1
                what = TYPE_IMG
                link = img['link']
                ext = img['type'].split('/')[1]
                if img['animated']:
                    what = TYPE_GIF
                    link = img['mp4'] if mp4_instead_gif else img['gifv'][:-1]
                    ext = 'mp4' if mp4_instead_gif else 'gif'
                story[number] = {'url': link, 'what': what, 'ext': ext}
            if len(story) == 1:
                return story[1]['what'], story[1]['url']
            return TYPE_ALBUM, story
        else:
            # Just imgur img
            img = imgur_client.get_image(path_parts[1].split('.')[0])
            if not img.animated:
                return TYPE_IMG, img.link
            else:
                if mp4_instead_gif:
                    return TYPE_GIF, img.mp4
                else:
                    # return 'gif', img.link
                    return TYPE_GIF, img.gifv[:-1]
    elif 'gfycat.com' in urlparse(url).netloc:
        rname = re.findall(r'gfycat.com\/(?:detail\/)?(\w*)', url)[0]
        try:
            r = requests.get(GFYCAT_GET + rname)
            if r.status_code != 200:
                logging.info('Gfy fail prevented!')
                return TYPE_OTHER, url
            urls = r.json()['gfyItem']
            if mp4_instead_gif:
                return TYPE_GIF, urls['mp4Url']
            else:
                return TYPE_GIF, urls['max5mbGif']
        except KeyError:
            logging.info('Gfy fail prevented!')
            return TYPE_OTHER, url
    else:
        return TYPE_OTHER, url
Exemplo n.º 19
0
from reportlab.platypus import SimpleDocTemplate, Paragraph, Image, Spacer, PageBreak
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from reportlab.lib.enums import TA_JUSTIFY
import requests
import shutil
import os

# trying to fix the error messages
import urllib3
urllib3.disable_warnings()

album = raw_input('Album ID:')
client = ImgurClient(client_id, client_secret)
album_data = client.get_album(album)
album_file = album_data.title.replace(' ', '_') + ".pdf"
doc = SimpleDocTemplate(album_file,
                        pagesize=letter,
                        rightMargin=25,
                        leftMargin=25,
                        topMargin=25,
                        bottomMargin=25)
ParagraphStyle(name='Normal',
               fontName="Verdana",
               fontSize=11,
               leading=15,
               alignment=TA_JUSTIFY,
               allowOrphans=0,
               spaceBefore=20,
               spaceAfter=20,
Exemplo n.º 20
0
class SpiffyTitles(callbacks.Plugin):
    """Displays link titles when posted in a channel"""
    threaded = True
    callBefore = ["Web"]
    link_cache = []
    handlers = {}
    wall_clock_timeout = 8
    max_request_retries = 3
    imgur_client = None
    
    def __init__(self, irc):
        self.__parent = super(SpiffyTitles, self)
        self.__parent.__init__(irc)
            
        self.wall_clock_timeout = self.registryValue("wallClockTimeoutInSeconds")
        self.default_handler_enabled = self.registryValue("defaultHandlerEnabled")
        
        self.add_handlers()
    
    def add_handlers(self):
        """
        Adds all handlers
        """
        self.add_youtube_handlers()
        self.add_imdb_handlers()
        self.add_imgur_handlers()
        self.add_coub_handlers()
        self.add_vimeo_handlers()
        self.add_dailymotion_handlers()
        self.add_wikipedia_handlers()
    
    def add_dailymotion_handlers(self):
        self.handlers["www.dailymotion.com"] = self.handler_dailymotion
    
    def add_vimeo_handlers(self):
        self.handlers["vimeo.com"] = self.handler_vimeo
    
    def add_coub_handlers(self):
        self.handlers["coub.com"] = self.handler_coub
    
    def add_wikipedia_handlers(self):
        self.handlers["en.wikipedia.org"] = self.handler_wikipedia

    def handler_dailymotion(self, url, info, channel):
        """
        Handles dailymotion links
        """
        dailymotion_handler_enabled = self.registryValue("dailymotionHandlerEnabled", channel=channel)
        log.debug("SpiffyTitles: calling dailymotion handler for %s" % url)
        title = None
        video_id = None
        
        """ Get video ID """
        if dailymotion_handler_enabled and "/video/" in info.path:
            video_id = info.path.lstrip("/video/").split("_")[0]
            
            if video_id is not None:
                api_url = "https://api.dailymotion.com/video/%s?fields=id,title,owner.screenname,duration,views_total" % video_id
                log.debug("SpiffyTitles: looking up dailymotion info: %s", api_url)
                agent = self.get_user_agent()
                headers = {
                    "User-Agent": agent
                }
                
                request = requests.get(api_url, headers=headers)
                
                ok = request.status_code == requests.codes.ok
                
                if ok:
                    response = json.loads(request.text)
                    
                    if response is not None and "title" in response:
                        video = response
                        dailymotion_template = Template(self.registryValue("dailymotionVideoTitleTemplate", channel=channel))
                        video["views_total"] = "{:,}".format(int(video["views_total"]))
                        video["duration"] = self.get_duration_from_seconds(video["duration"])
                        video["ownerscreenname"] = video["owner.screenname"]
                        
                        title = dailymotion_template.render(video)
                    else:
                        log.debug("SpiffyTitles: received unexpected payload from video: %s" % api_url)
                else:
                    log.error("SpiffyTitles: dailymotion handler returned %s: %s" % (request.status_code, request.text[:200]))
        
        if title is None:
            log.debug("SpiffyTitles: could not get dailymotion info for %s" % url)
            
            return self.handler_default(url, channel)
        else:
            return title
    
    def handler_vimeo(self, url, domain, channel):
        """
        Handles Vimeo links
        """
        vimeo_handler_enabled = self.registryValue("vimeoHandlerEnabled", channel=channel)
        log.debug("SpiffyTitles: calling vimeo handler for %s" % url)
        title = None
        video_id = None
        
        """ Get video ID """
        if vimeo_handler_enabled:
            result = re.search(r'^(http(s)://)?(www\.)?(vimeo\.com/)?(\d+)', url)
            
            if result is not None:
                video_id = result.group(5)
            
            if video_id is not None:
                api_url = "https://vimeo.com/api/v2/video/%s.json" % video_id
                log.debug("SpiffyTitles: looking up vimeo info: %s", api_url)
                agent = self.get_user_agent()
                headers = {
                    "User-Agent": agent
                }
                
                request = requests.get(api_url, headers=headers)
                
                ok = request.status_code == requests.codes.ok
                
                if ok:
                    response = json.loads(request.text)
                    
                    if response is not None and "title" in response[0]:
                        video = response[0]
                        vimeo_template = Template(self.registryValue("vimeoTitleTemplate", channel=channel))
                        
                        """ 
                        Some videos do not have this information available
                        """
                        if "stats_number_of_plays" in video:
                            video["stats_number_of_plays"] = "{:,}".format(int(video["stats_number_of_plays"]))
                        else:
                            video["stats_number_of_plays"] = 0
                        
                        if "stats_number_of_comments" in video:
                            video["stats_number_of_comments"] = "{:,}".format(int(video["stats_number_of_comments"]))
                        else:
                            video["stats_number_of_comments"] = 0
                        
                        video["duration"] = self.get_duration_from_seconds(video["duration"])
                        
                        title = vimeo_template.render(video)
                    else:
                        log.debug("SpiffyTitles: received unexpected payload from video: %s" % api_url)
                else:
                    log.error("SpiffyTitles: vimeo handler returned %s: %s" % (request.status_code, request.text[:200]))
        
        if title is None:
            log.debug("SpiffyTitles: could not get vimeo info for %s" % url)
            
            return self.handler_default(url, channel)
        else:
            return title
    
    def handler_coub(self, url, domain, channel):
        """
        Handles coub.com links
        """
        coub_handler_enabled = self.registryValue("coubHandlerEnabled", channel=channel)
        log.debug("SpiffyTitles: calling coub handler for %s" % url)
        title = None
        
        """ Get video ID """
        if coub_handler_enabled and "/view/" in url:
            video_id = url.split("/view/")[1]
            
            """ Remove any query strings """
            if "?" in video_id:
                video_id = video_id.split("?")[0]
                
            api_url = "http://coub.com/api/v2/coubs/%s" % video_id
            agent = self.get_user_agent()
            headers = {
                "User-Agent": agent
            }
            
            request = requests.get(api_url, headers=headers)
            
            ok = request.status_code == requests.codes.ok
            
            if ok:
                response = json.loads(request.text)
                
                if response:
                    video = response
                    coub_template = Template(self.registryValue("coubTemplate"))
                    
                    video["likes_count"] = "{:,}".format(int(video["likes_count"]))
                    video["recoubs_count"] = "{:,}".format(int(video["recoubs_count"]))
                    video["views_count"] = "{:,}".format(int(video["views_count"]))
                    
                    title = coub_template.render(video)
            else:
                log.error("SpiffyTitles: coub handler returned %s: %s" % (request.status_code, request.text[:200]))
        
        if title is None:
            if coub_handler_enabled:
                log.debug("SpiffyTitles: %s does not appear to be a video link!" % url)
            
            return self.handler_default(url, channel)
        else:
            return title
    
    def add_imgur_handlers(self):
        # Images mostly
        self.handlers["i.imgur.com"] = self.handler_imgur_image
        
        # Albums, galleries, etc
        self.handlers["imgur.com"] = self.handler_imgur
    
    def initialize_imgur_client(self, channel):
        """
        Check if imgur client id or secret are set, and if so initialize
        imgur API client
        """
        if self.imgur_client is None:
            imgur_client_id = self.registryValue("imgurClientID")
            imgur_client_secret = self.registryValue("imgurClientSecret")
            imgur_handler_enabled = self.registryValue("imgurHandlerEnabled", channel=channel)
            
            if imgur_handler_enabled and imgur_client_id and imgur_client_secret:
                log.debug("SpiffyTitles: enabling imgur handler")

                # Initialize API client
                try:
                    from imgurpython import ImgurClient
                    from imgurpython.helpers.error import ImgurClientError
                    
                    try:
                        self.imgur_client = ImgurClient(imgur_client_id, imgur_client_secret)                    
                    except ImgurClientError as e:
                        log.error("SpiffyTitles: imgur client error: %s" % (e.error_message))                    
                except ImportError as e:
                    log.error("SpiffyTitles ImportError: %s" % str(e))
            else:
                log.debug("SpiffyTitles: imgur handler disabled or empty client id/secret")
    
    def doPrivmsg(self, irc, msg):
        """
        Observe each channel message and look for links
        """
        channel = msg.args[0]
        ignore_actions = self.registryValue("ignoreActionLinks", channel=msg.args[0])
        is_channel = irc.isChannel(channel)
        is_ctcp = ircmsgs.isCtcp(msg)        
        message = msg.args[1]
        title = None
        bot_nick = irc.nick
        origin_nick = msg.nick
        is_message_from_self = origin_nick.lower() == bot_nick.lower()
        requires_capability = len(str(self.registryValue("requireCapability", channel=msg.args[0]))) > 0

        if is_message_from_self:
            return

        """
        Check if we require a capability to acknowledge this link
        """
        if requires_capability:
            user_has_capability = self.user_has_capability(msg)

            if not user_has_capability:
                return

        """
        Configuration option determines whether we should
        ignore links that appear within an action
        """
        if is_ctcp and ignore_actions:
            return

        if is_channel:
            channel_is_allowed = self.is_channel_allowed(channel)            
            url = self.get_url_from_message(message)
            ignore_match = self.message_matches_ignore_pattern(message)
            
            if ignore_match:
                log.debug("SpiffyTitles: ignoring message due to linkMessagePattern match")
                return
            
            if url:
                # Check if channel is allowed based on white/black list restrictions
                if not channel_is_allowed:
                    log.debug("SpiffyTitles: not responding to link in %s due to black/white list restrictions" % (channel))
                    return
                
                info = urlparse(url)
                domain = info.netloc
                is_ignored = self.is_ignored_domain(domain)
                
                if is_ignored:
                    log.debug("SpiffyTitles: URL ignored due to domain blacklist match: %s" % url)
                    return
                
                is_whitelisted_domain = self.is_whitelisted_domain(domain)
                
                if self.registryValue("whitelistDomainPattern") and not is_whitelisted_domain:
                    log.debug("SpiffyTitles: URL ignored due to domain whitelist mismatch: %s" % url)
                    return
                
                title = self.get_title_by_url(url, channel)
                
                if title is not None and title:
                    ignore_match = self.title_matches_ignore_pattern(title, channel)
                    
                    if ignore_match:
                        return
                    else:
                        irc.sendMsg(ircmsgs.privmsg(channel, title))
                else:
                    if self.default_handler_enabled:
                        log.debug("SpiffyTitles: could not get a title for %s" % (url))
                    else:   
                        log.debug("SpiffyTitles: could not get a title for %s but default handler is disabled" % (url))
    
    def get_title_by_url(self, url, channel):
        """
        Retrieves the title of a website based on the URL provided
        """
        info = urlparse(url)
        domain = info.netloc
        title = None
        
        """
        Check if we have this link cached according to the cache lifetime. If so, serve
        link from the cache instead of calling handlers.
        """
        cached_link = self.get_link_from_cache(url)
        
        if cached_link is not None:                    
            title = cached_link["title"]
        else:
            if domain in self.handlers:
                handler = self.handlers[domain]                        
                title = handler(url, info, channel)
            else:
                if self.default_handler_enabled:
                    title = self.handler_default(url, channel)
        
        if title is not None:
            title = self.get_formatted_title(title, channel)
            
            # Update link cache
            log.debug("SpiffyTitles: caching %s" % (url))
            now = datetime.datetime.now()
            self.link_cache.append({
                "url": url,
                "timestamp": now,
                "title": title
            })
        
        return title

    def t(self, irc, msg, args, query):
        """
        Retrieves title for a URL on demand
        """
        message = msg.args[1]
        channel = msg.args[0]
        url = self.get_url_from_message(message)
        title = None
        error_message = self.registryValue("onDemandTitleError", channel=channel)
        
        try:
            if url:
                title = self.get_title_by_url(query, channel)
        except:
            pass
        
        if title is not None and title:
            irc.sendMsg(ircmsgs.privmsg(channel, title))
        else:
            irc.sendMsg(ircmsgs.privmsg(channel, error_message))
    
    t = wrap(t, ['text'])
    
    def get_link_from_cache(self, url):
        """
        Looks for a URL in the link cache and returns info about if it's not stale
        according to the configured cache lifetime, or None.
        
        If linkCacheLifetimeInSeconds is 0, then cache is disabled and we can 
        immediately return
        """
        cache_lifetime_in_seconds = int(self.registryValue("linkCacheLifetimeInSeconds"))
        
        if cache_lifetime_in_seconds == 0:
            return
        
        # No cache yet
        if len(self.link_cache) == 0:
            return
        
        cached_link = None
        now = datetime.datetime.now()        
        stale = False
        seconds = 0
        
        for link in self.link_cache:
            if link["url"] == url:
                cached_link = link
                break
        
        # Found link, check timestamp
        if cached_link is not None:
            seconds = (now - cached_link["timestamp"]).total_seconds()
            stale = seconds >= cache_lifetime_in_seconds
        
        if stale:
            log.debug("SpiffyTitles: %s was sent %s seconds ago" % (url, seconds))
        else:
            log.debug("SpiffyTitles: serving link from cache: %s" % (url))
            return cached_link

    def add_imdb_handlers(self):
        """
        Enables meta info about IMDB links through the OMDB API
        """
        self.handlers["www.imdb.com"] = self.handler_imdb
        self.handlers["imdb.com"] = self.handler_imdb
    
    def add_youtube_handlers(self):
        """
        Adds handlers for Youtube videos. The handler is matched based on the
        domain used in the URL.
        """
        self.handlers["youtube.com"] = self.handler_youtube
        self.handlers["www.youtube.com"] = self.handler_youtube
        self.handlers["youtu.be"] = self.handler_youtube
        self.handlers["m.youtube.com"] = self.handler_youtube
    
    def is_channel_allowed(self, channel):
        """
        Checks channel whitelist and blacklist to determine if the current
        channel is allowed to display titles.
        """
        channel = channel.lower()
        is_allowed = False
        white_list = self.filter_empty(self.registryValue("channelWhitelist"))
        black_list = self.filter_empty(self.registryValue("channelBlacklist"))
        white_list_empty = len(white_list) == 0
        black_list_empty = len(black_list) == 0
        
        # Most basic case, which is that both white and blacklist are empty. Any channel is allowed.
        if white_list_empty and black_list_empty:
            is_allowed = True
        
        # If there is a white list, blacklist is ignored.
        if white_list:
            is_allowed = channel in white_list
        
        # Finally, check blacklist
        if not white_list and black_list:
            is_allowed = channel not in black_list
        
        return is_allowed
    
    def filter_empty(self, input):
        """
        Remove all empty strings from a list
        """
        return set([channel for channel in input if len(channel.strip())])
    
    def is_ignored_domain(self, domain):
        """
        Checks domain against a regular expression
        """
        pattern = self.registryValue("ignoredDomainPattern")
        
        if pattern:
            log.debug("SpiffyTitles: matching %s against %s" % (domain, str(pattern)))
            
            try:
                pattern_search_result = re.search(pattern, domain)
                
                if pattern_search_result is not None:
                    match = pattern_search_result.group()
                    
                    return match
            except re.Error:
                log.error("SpiffyTitles: invalid regular expression: %s" % (pattern))
    
    def is_whitelisted_domain(self, domain):
        """
        Checks domain against a regular expression
        """
        pattern = self.registryValue("whitelistDomainPattern")
        
        if pattern:
            log.debug("SpiffyTitles: matching %s against %s" % (domain, str(pattern)))
            
            try:
                pattern_search_result = re.search(pattern, domain)
                
                if pattern_search_result is not None:
                    match = pattern_search_result.group()
                    
                    return match
            except re.Error:
                log.error("SpiffyTitles: invalid regular expression: %s" % (pattern))
    
    def get_video_id_from_url(self, url, info):
        """
        Get YouTube video ID from URL
        """
        try:
            path = info.path
            domain = info.netloc
            video_id = ""
            
            if domain == "youtu.be":
                video_id = path.split("/")[1]
            else:
                parsed = cgi.parse_qsl(info.query)
                params = dict(parsed)
                
                if "v" in params:
                    video_id = params["v"]
            
            if video_id:
                return video_id
            else:
                log.error("SpiffyTitles: error getting video id from %s" % (url))
        
        except IndexError as e:
            log.error("SpiffyTitles: error getting video id from %s (%s)" % (url, str(e)))

    def handler_youtube(self, url, domain, channel):
        """
        Uses the Youtube API to provide additional meta data about
        Youtube Video links posted.
        """
        youtube_handler_enabled = self.registryValue("youtubeHandlerEnabled", channel=channel)
        developer_key = self.registryValue("youtubeDeveloperKey")
        
        if not youtube_handler_enabled:
            return None
        
        if not developer_key:
            log.info("SpiffyTitles: no Youtube developer key set! Check the documentation for instructions.")
            return None
        
        log.debug("SpiffyTitles: calling Youtube handler for %s" % (url))
        video_id = self.get_video_id_from_url(url, domain)
        yt_template = Template(self.registryValue("youtubeTitleTemplate", channel=channel))
        title = ""
        
        if video_id:
            options = {
                "part": "snippet,statistics,contentDetails",
                "maxResults": 1,
                "key": developer_key,
                "id": video_id
            }
            encoded_options = urlencode(options)
            api_url = "https://www.googleapis.com/youtube/v3/videos?%s" % (encoded_options)
            agent = self.get_user_agent()
            headers = {
                "User-Agent": agent
            }
            
            log.debug("SpiffyTitles: requesting %s" % (api_url))
            
            request = requests.get(api_url, headers=headers)            
            ok = request.status_code == requests.codes.ok
            
            if ok:
                response = json.loads(request.text)
                
                if response:
                    try:
                        if response["pageInfo"]["totalResults"] > 0:
                            items = response["items"]
                            video = items[0]
                            snippet = video["snippet"]
                            title = snippet["title"]
                            statistics = video["statistics"]
                            view_count = 0
                            like_count = 0
                            dislike_count = 0
                            comment_count = 0
                            favorite_count = 0

                            if "viewCount" in statistics:
                                view_count = "{:,}".format(int(statistics["viewCount"]))
                            
                            if "likeCount" in statistics:
                                like_count = "{:,}".format(int(statistics["likeCount"]))

                            if "dislikeCount" in statistics:
                                dislike_count = "{:,}".format(int(statistics["dislikeCount"]))

                            if "favoriteCount" in statistics:
                                favorite_count = "{:,}".format(int(statistics["favoriteCount"]))

                            if "commentCount" in statistics:
                                comment_count = "{:,}".format(int(statistics["commentCount"]))
                            
                            channel_title = snippet["channelTitle"]
                            duration_seconds = self.get_total_seconds_from_duration(video["contentDetails"]["duration"])

                            """
                            #23 - If duration is zero, then it"s a LIVE video
                            """
                            if duration_seconds > 0:
                                duration = self.get_duration_from_seconds(duration_seconds)
                            else:
                                duration = "LIVE"
                            
                            timestamp = self.get_timestamp_from_youtube_url(url)
                            yt_logo = self.get_youtube_logo()
                            
                            compiled_template = yt_template.render({
                                "title": title,
                                "duration": duration,
                                "timestamp": timestamp,
                                "view_count": view_count,
                                "like_count": like_count,
                                "dislike_count": dislike_count,
                                "comment_count": comment_count,
                                "favorite_count": favorite_count,
                                "channel_title": channel_title,
                                "yt_logo": yt_logo
                            })
                            
                            title = compiled_template
                        else:
                            log.debug("SpiffyTitles: video appears to be private; no results!")
                        
                    except IndexError as e:
                        log.error("SpiffyTitles: IndexError parsing Youtube API JSON response: %s" % (str(e)))
                else:
                    log.error("SpiffyTitles: Error parsing Youtube API JSON response")
            else:
                log.error("SpiffyTitles: Youtube API HTTP %s: %s" % (request.status_code,
                                                                         request.text))
        
        # If we found a title, return that. otherwise, use default handler
        if title:
            return title
        else:
            log.debug("SpiffyTitles: falling back to default handler")
            
            return self.handler_default(url, channel)
    
    def get_duration_from_seconds(self, duration_seconds):
        m, s = divmod(duration_seconds, 60)
        h, m = divmod(m, 60)
        
        duration = "%02d:%02d" % (m, s)
        
        """ Only include hour if the video is at least 1 hour long """
        if h > 0:
            duration = "%02d:%s" % (h, duration)
        
        return duration
    
    def get_youtube_logo(self):
        colored_letters = [
            "%s" % ircutils.mircColor("You", fg="red", bg="white"),
            "%s" % ircutils.mircColor("Tube", fg="white", bg="red")
        ]
                        
        yt_logo = "".join(colored_letters)
        
        return yt_logo
      
    def get_total_seconds_from_duration(self, input):
        """
        Duration comes in a format like this: PT4M41S which translates to
        4 minutes and 41 seconds. This method returns the total seconds
        so that the duration can be parsed as usual.
        """
        pattern = regex  = re.compile("""
                   (?P<sign>    -?) P
                (?:(?P<years>  \d+) Y)?
                (?:(?P<months> \d+) M)?
                (?:(?P<days>   \d+) D)?
            (?:                     T
                (?:(?P<hours>  \d+) H)?
                (?:(?P<minutes>\d+) M)?
                (?:(?P<seconds>\d+) S)?
            )?
            """, re.VERBOSE)
        duration = regex.match(input).groupdict(0)
        
        delta = timedelta(hours=int(duration['hours']),
                          minutes=int(duration['minutes']),
                          seconds=int(duration['seconds']))
        
        return delta.total_seconds()

    def get_timestamp_from_youtube_url(self, url):
        """
        Get YouTube timestamp
        """
        pattern = r"[?&]t=([^&]+)"
        match = re.search(pattern, url)

        if match:
            timestamp = match.group(1).upper()
            try:
                seconds = float(timestamp)
            except ValueError:
                seconds = self.get_total_seconds_from_duration("PT" + timestamp)

            if seconds > 0:
                return self.get_duration_from_seconds(seconds)
        else:
            return ""        
        
    def handler_default(self, url, channel):
        """
        Default handler for websites
        """
        default_handler_enabled = self.registryValue("defaultHandlerEnabled", channel=channel)
        
        if default_handler_enabled:
            log.debug("SpiffyTitles: calling default handler for %s" % (url))
            default_template = Template(self.registryValue("defaultTitleTemplate", channel=channel))
            html = self.get_source_by_url(url)
            
            if html is not None and html:
                title = self.get_title_from_html(html)
                
                if title is not None:
                    title_template = default_template.render(title=title)
                    
                    return title_template
        else:
            log.debug("SpiffyTitles: default handler fired but doing nothing because disabled")
    
    def handler_imdb(self, url, info, channel):
        """
        Handles imdb.com links, querying the OMDB API for additional info
        
        Typical IMDB URL: http://www.imdb.com/title/tt2467372/
        """
        headers = self.get_headers()
        result = None
        
        if not self.registryValue("imdbHandlerEnabled", channel=channel):
            log.debug("SpiffyTitles: IMDB handler disabled. Falling back to default handler.")
            
            return self.handler_default(url, channel)
        
        # Don't care about query strings
        if "?" in url:
            url = url.split("?")[0]
        
        # We can only accommodate a specific format of URL here
        if "/title/" in url:
            imdb_id = url.split("/title/")[1].rstrip("/")
            omdb_url = "http://www.omdbapi.com/?i=%s&plot=short&r=json&tomatoes=true" % (imdb_id)
            
            try:
                request = requests.get(omdb_url, timeout=10, headers=headers)
                
                if request.status_code == requests.codes.ok:
                    response = json.loads(request.text)
                    result = None
                    imdb_template = Template(self.registryValue("imdbTemplate"))
                    not_found = "Error" in response
                    unknown_error = response["Response"] != "True"
                    
                    if not_found or unknown_error:
                        log.debug("SpiffyTitles: OMDB error for %s" % (omdb_url))
                    else:
                        result = imdb_template.render(response)
                else:
                    log.error("SpiffyTitles OMDB API %s - %s" % (request.status_code, request.text)) 
            
            except requests.exceptions.Timeout as e:
                log.error("SpiffyTitles imdb Timeout: %s" % (str(e)))
            except requests.exceptions.ConnectionError as e:
                log.error("SpiffyTitles imdb ConnectionError: %s" % (str(e)))
            except requests.exceptions.HTTPError as e:
                log.error("SpiffyTitles imdb HTTPError: %s" % (str(e)))
        
        if result is not None:
            return result
        else:
            log.debug("SpiffyTitles: IMDB handler failed. calling default handler")
            
            return self.handler_default(url, channel)
    
    def handler_wikipedia(self, url, domain, channel):
        """
        Queries wikipedia API for article extracts.
        """
        wikipedia_handler_enabled = self.registryValue("wikipedia.enabled", channel=channel)
        if not wikipedia_handler_enabled:
            return self.handler_default(url, channel)

        self.log.debug("SpiffyTitles: calling Wikipedia handler for %s" % (url))

        pattern = r"/(?:w(?:iki))/(?P<page>[^/]+)$"
        info = urlparse(url)
        match = re.search(pattern, info.path)
        if not match:
            self.log.debug("SpiffyTitles: no title found.")
            return self.handler_default(url, channel)
        elif info.fragment and self.registryValue("wikipedia.ignoreSectionLinks", channel=channel):
            self.log.debug("SpiffyTitles: ignoring section link.")
            return self.handler_default(url, channel)
        else:
            page_title = match.groupdict()['page']

        default_api_params = {
            "format":      "json",
            "action":      "query",
            "prop":        "extracts",
            "exsentences": "2",
            "exlimit":     "1",
            "exintro":     "",
            "explaintext": ""
        }
        extra_params = dict(parse_qsl('&'.join(self.registryValue("wikipedia.apiParams", channel=channel))))
        title_param  = { self.registryValue("wikipedia.titleParam", channel=channel): page_title }

        # merge dicts
        api_params = default_api_params.copy()
        api_params.update(extra_params)
        api_params.update(title_param)
        api_url = "https://en.wikipedia.org/w/api.php?%s" % ('&'.join("%s=%s" % (key, val) for (key,val) in api_params.iteritems()))

        agent = self.get_user_agent()
        headers = {
            "User-Agent": agent
        }
        extract = ""

        self.log.debug("SpiffyTitles: requesting %s" % (api_url))

        request = requests.get(api_url, headers=headers)            
        ok = request.status_code == requests.codes.ok
        
        if ok:
            response = json.loads(request.text)
            
            if response:
                try:
                    extract = response['query']['pages'].values()[0]['extract']
                except KeyError as e:
                    self.log.error("SpiffyTitles: KeyError parsing Wikipedia API JSON response: %s" % (str(e)))
            else:
                self.log.error("SpiffyTitles: Error parsing Wikipedia API JSON response")
        else:
            self.log.error("SpiffyTitles: Wikipedia API HTTP %s: %s" % (request.status_code, request.text))

        if extract:
            if (self.registryValue("wikipedia.removeParentheses")):
                extract = re.sub(r' ?\([^)]*\)', '', extract)
            max_chars = self.registryValue("wikipedia.maxChars", channel=channel)
            if len(extract) > max_chars:
                extract = extract[:max_chars - 3].rsplit(' ', 1)[0].rstrip(',.') + '...'

            wikipedia_template = Template(self.registryValue("wikipedia.extractTemplate", channel=channel))
            return wikipedia_template.render({"extract": extract})
        else:
            self.log.debug("SpiffyTitles: falling back to default handler")
            
            return self.handler_default(url, channel)


    def is_valid_imgur_id(self, input):
        """
        Tests if input matches the typical imgur id, which seems to be alphanumeric. Images, galleries,
        and albums all share their format in their identifier.
        """
        match = re.match(r"[a-z0-9]+", input, re.IGNORECASE)
        
        return match is not None
    
    def handler_imgur(self, url, info, channel):
        """
        Queries imgur API for additional information about imgur links.

        This handler is for any imgur.com domain.
        """
        self.initialize_imgur_client(channel)
        
        is_album = info.path.startswith("/a/")
        is_gallery = info.path.startswith("/gallery/")
        is_image_page = not is_album and not is_gallery and re.match(r"^\/[a-zA-Z0-9]+", info.path)
        result = None
        
        if is_album:
            result = self.handler_imgur_album(url, info, channel)
        #elif is_image_page:
        #    result = self.handler_imgur_image(url, info)
        else:
            result = self.handler_default(url, channel)
        
        return result
    
    def handler_imgur_album(self, url, info, channel):
        """
        Handles retrieving information about albums from the imgur API.
        
        imgur provides the following information about albums: https://api.imgur.com/models/album
        """
        from imgurpython.helpers.error import ImgurClientRateLimitError
        from imgurpython.helpers.error import ImgurClientError
        self.initialize_imgur_client(channel)
        
        if self.imgur_client:
            album_id = info.path.split("/a/")[1]
            
            """ If there is a query string appended, remove it """
            if "?" in album_id:
                album_id = album_id.split("?")[0]
            
            if self.is_valid_imgur_id(album_id):
                log.debug("SpiffyTitles: found imgur album id %s" % (album_id))
                
                try:
                    album = self.imgur_client.get_album(album_id)
                    
                    if album:
                        imgur_album_template = Template(self.registryValue("imgurAlbumTemplate", channel=channel))
                        compiled_template = imgur_album_template.render({
                            "title": album.title,
                            "section": album.section,
                            "view_count": "{:,}".format(album.views),
                            "image_count": "{:,}".format(album.images_count),
                            "nsfw": album.nsfw
                        })
                        
                        return compiled_template
                    else:
                        log.error("SpiffyTitles: imgur album API returned unexpected results!")

                except ImgurClientRateLimitError as e:
                    log.error("SpiffyTitles: imgur rate limit error: %s" % (e.error_message))
                except ImgurClientError as e:
                    log.error("SpiffyTitles: imgur client error: %s" % (e.error_message))
            else:
                log.debug("SpiffyTitles: unable to determine album id for %s" % (url))
        else:
            return self.handler_default(url, channel)
    
    def handler_imgur_image(self, url, info, channel):
        """
        Handles retrieving information about images from the imgur API.
        
        Used for both direct images and imgur.com/some_image_id_here type links, as
        they're both single images.
        """
        self.initialize_imgur_client(channel)
        
        from imgurpython.helpers.error import ImgurClientRateLimitError
        from imgurpython.helpers.error import ImgurClientError
        title = None
        
        if self.imgur_client:
            """ 
            If there is a period in the path, it's a direct link to an image. If not, then
            it's a imgur.com/some_image_id_here type link
            """
            if "." in info.path:
                path = info.path.lstrip("/")
                image_id = path.split(".")[0]
            else:
                image_id = info.path.lstrip("/")
            
            if self.is_valid_imgur_id(image_id):
                log.debug("SpiffyTitles: found image id %s" % (image_id))
                
                try:
                    image = self.imgur_client.get_image(image_id)
                    
                    if image:
                        imgur_template = Template(self.registryValue("imgurTemplate", channel=channel))
                        readable_file_size = self.get_readable_file_size(image.size)
                        compiled_template = imgur_template.render({
                            "title": image.title,
                            "type": image.type,
                            "nsfw": image.nsfw,
                            "width": image.width,
                            "height": image.height,
                            "view_count": "{:,}".format(image.views),
                            "file_size": readable_file_size,
                            "section": image.section
                        })
                        
                        title = compiled_template
                    else:
                        log.error("SpiffyTitles: imgur API returned unexpected results!")
                except ImgurClientRateLimitError as e:
                    log.error("SpiffyTitles: imgur rate limit error: %s" % (e.error_message))
                except ImgurClientError as e:
                    log.error("SpiffyTitles: imgur client error: %s" % (e.error_message))
            else:
                log.error("SpiffyTitles: error retrieving image id for %s" % (url))
        
        if title is not None:
            return title
        else:
            return self.handler_default(url, channel)
    
    def get_readable_file_size(self, num, suffix="B"):
        """
        Returns human readable file size
        """
        for unit in ["","Ki","Mi","Gi","Ti","Pi","Ei","Zi"]:
            if abs(num) < 1024.0:
                return "%3.1f%s%s" % (num, unit, suffix)
            num /= 1024.0
        return "%.1f%s%s" % (num, "Yi", suffix)
    
    def get_formatted_title(self, title, channel):
        """
        Remove cruft from title and apply bold if applicable
        """
        useBold = self.registryValue("useBold", channel=channel)
        
        # Replace anywhere in string
        title = title.replace("\n", " ")
        title = title.replace("\t", " ")
        title = re.sub(" +", " ", title)
        
        if useBold:
            title = ircutils.bold(title)
        
        title = title.strip()
        
        return title
    
    def get_title_from_html(self, html):
        """
        Retrieves value of <title> tag from HTML
        """
        soup = BeautifulSoup(html, "lxml")
        
        if soup is not None:
            """
            Some websites have more than one title tag, so get all of them 
            and take the last value.
            """
            head = soup.find("head")
            titles = head.find_all("title")
            
            if titles is not None and len(titles):                
                title_text = titles[-1].get_text()
                
                if len(title_text):
                    stripped_title = title_text.strip()
                    
                    return stripped_title
    
    @timeout_decorator.timeout(wall_clock_timeout)
    def get_source_by_url(self, url, retries=1):
        """
        Get the HTML of a website based on a URL
        """
        max_retries = self.registryValue("maxRetries")
        
        if retries is None:
            retries = 1
        
        if retries >= max_retries:
            log.debug("SpiffyTitles: hit maximum retries for %s" % url)
            
            return None
        
        log.debug("SpiffyTitles: attempt #%s for %s" % (retries, url))
        
        try:
            headers = self.get_headers()
            
            log.debug("SpiffyTitles: requesting %s" % (url))
            
            request = requests.get(url, headers=headers, timeout=10, allow_redirects=True)
            
            if request.status_code == requests.codes.ok:
                # Check the content type which comes in the format: "text/html; charset=UTF-8"
                content_type = request.headers.get("content-type").split(";")[0].strip()
                acceptable_types = self.registryValue("mimeTypes")
                
                log.debug("SpiffyTitles: content type %s" % (content_type))
                
                if content_type in acceptable_types:
                    text = request.content
                    
                    if text:
                        return text
                    else:
                        log.debug("SpiffyTitles: empty content from %s" % (url))                        
                
                else:
                    log.debug("SpiffyTitles: unacceptable mime type %s for url %s" % (content_type, url))
            else:
                log.error("SpiffyTitles HTTP response code %s - %s" % (request.status_code, 
                                                                            request.content))
        
        except timeout_decorator.TimeoutError:
            log.error("SpiffyTitles: wall timeout!")
            
            self.get_source_by_url(url, retries+1)        
        except requests.exceptions.MissingSchema as e:
            urlWithSchema = "http://%s" % (url)
            log.error("SpiffyTitles missing schema. Retrying with %s" % (urlWithSchema))
            return self.get_source_by_url(urlWithSchema)
        except requests.exceptions.Timeout as e:
            log.error("SpiffyTitles Timeout: %s" % (str(e)))
            
            self.get_source_by_url(url, retries+1)            
        except requests.exceptions.ConnectionError as e:
            log.error("SpiffyTitles ConnectionError: %s" % (str(e)))
            
            self.get_source_by_url(url, retries+1)            
        except requests.exceptions.HTTPError as e:
            log.error("SpiffyTitles HTTPError: %s" % (str(e)))
        except requests.exceptions.InvalidURL as e:
            log.error("SpiffyTitles InvalidURL: %s" % (str(e)))
    
    def get_headers(self):
        agent = self.get_user_agent()
        self.accept_language = self.registryValue("language")
        
        headers = {
            "User-Agent": agent,
            "Accept-Language": ";".join((self.accept_language, "q=1.0"))
        }
        
        return headers
    
    def get_user_agent(self):
        """
        Returns a random user agent from the ones available
        """
        agents = self.registryValue("userAgents")
        
        return random.choice(agents)
    
    def message_matches_ignore_pattern(self, input):
        """
        Checks message against linkMessageIgnorePattern to determine
        whether the message should be ignored.
        """
        match = False
        pattern = self.registryValue("linkMessageIgnorePattern")
        
        if pattern:
            match = re.search(pattern, input)
        
        return match
    
    def title_matches_ignore_pattern(self, input, channel):
        """
        Checks message against ignoredTitlePattern to determine
        whether the title should be ignored.
        """
        match = False
        pattern = self.registryValue("ignoredTitlePattern", channel=channel)
        
        if pattern:
            match = re.search(pattern, input)

            if match:
                log.debug("SpiffyTitles: title %s matches ignoredTitlePattern for %s" % (input, channel))
        
        return match
    
    def get_url_from_message(self, input):
        """
        Find the first string that looks like a URL from the message
        """
        url_re = self.registryValue("urlRegularExpression")
        match = re.search(url_re, input)
        
        if match:
            raw_url = match.group(0).strip()
            url = self.remove_control_characters(unicode(raw_url))

            return url
    
    def remove_control_characters(self, s):
        return "".join(ch for ch in s if unicodedata.category(ch)[0]!="C")

    def user_has_capability(self, msg):
        channel = msg.args[0]
        mask = msg.prefix
        required_capability = self.registryValue("requireCapability")
        cap = ircdb.makeChannelCapability(channel, required_capability)
        has_cap = ircdb.checkCapability(mask, cap, ignoreDefaultAllow=True)

        if has_cap:
            log.debug("SpiffyTitles: %s has required capability '%s'" % (mask, required_capability))
        else:
            log.debug("SpiffyTitles: %s does NOT have required capability '%s'" % (mask, required_capability))

        return has_cap
for link in raw_links:

    # Check if imgur is in the reddit link's url
    if "imgur" not in link:
        continue

    file_extension = link.split(".")[-1]

    # Different ways to handle images, image sources, and albums/galleries
    if "jpg" in file_extension or "png" in file_extension:
        img_links.append(link)
    elif "gallery" in link.split("/") or "a" in link.split("/"):
        for index, value in enumerate(link.split("/")):
            if value == "gallery" or value == "a":
                imgur_album = client.get_album(link.split("/")[index + 1])
                break
        images = imgur_album.images
        for image in images:
            img_links.append(image["link"])
    else:
        imgur_r = urllib.urlopen(link).read()
        imgur_soup = BeautifulSoup(imgur_r, "lxml")
        imgur_link = imgur_soup.find("div", {"class": "post-image"}).find("a")["href"]
        if "//i.imgur.com" in imgur_link:
            img_links.append("https:" + imgur_link)


# Iterate through compiled list of links to save and name images
img_number = 0
Exemplo n.º 22
0
class ImgurDownloader:
    """Handler for Imgur downloads.

    Attributes
    ----------
    client : ImgurClient
        Instance of an Imgur API connection.

    """
    def __init__(self, client_id, client_secret):
        self.client = ImgurClient(client_id, client_secret)

    #FIXME: Implement this
    def check_rate_limit(self):
        pass

    def get_imgur_id(self, url):
        """Get an Imgur id from a url.

        Returns
        -------
        imgur_id : string
            The id of the content at the url.

        """

        if "imgur" not in url:
            return None

        imgur_id = url[url.rfind('/') + 1:]

        # Remove the file extension if it exists.
        extension_index = imgur_id.find('.')
        if extension_index != -1:
            imgur_id = imgur_id[:extension_index]

        return imgur_id

    #FIXME: Add error checking
    def download_album(self, url, output_dirpath):
        """Downloads the imgur album from the given url.

        Parameters
        ----------
        url : string
            URL for the imgur album.

        output_dirpath : pathlib.Path
            Path to the directory for saving images.

        Returns
        -------
        success : bool
            Whether the album downloaded successfully.

        """

        if "imgur.com/a/" not in url:
            return False

        imgur_id = self.get_imgur_id(url)
        album = self.client.get_album(imgur_id)

        # Create a directory for just the album.
        output_dir_str = str(output_dirpath)
        if not output_dir_str.endswith('/'):
            output_dir_str = output_dir_str + '/'

        if album.title:
            output_dir_str = output_dir_str + album.title + '/'
        else:
            output_dir_str = output_dir_str + imgur_id + '/'

        output_dirpath = pathlib.Path(output_dir_str)
        output_dirpath.mkdir(parents=True, exist_ok=True)

        for image in album.images:
            if type(image) is dict:
                image_id = image["id"]
                image_type = image["type"]
                image_link = image["link"]
            else:
                image_id = image.id
                image_type = image.type
                image_link = image.link

            output_filename = output_dir_str + image_id + " - imgur." + image_type[
                6:]

            with open(output_filename, 'wb') as handle:
                response = requests.get(image_link, stream=True)
                if not response.ok:
                    print(response)
                    return False

                for block in response.iter_content(1024):
                    if not block:
                        break
                    handle.write(block)

        return True

        # FIXME: Implement this
        def download_gallery(self, url, output_path):
            return False
Exemplo n.º 23
0
class Imgur(Plugin):
    CONFIG_DEFAULTS = {
        'client_id': None,
        'client_secret': None,
    }

    CONFIG_ENVVARS = {
        'client_id': ['IMGUR_CLIENT_ID'],
        'client_secret': ['IMGUR_CLIENT_SECRET'],
    }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.client = ImgurClient(self.config_get('client_id'),
                                  self.config_get('client_secret'))

    @Plugin.integrate_with('linkinfo')
    def integrate_with_linkinfo(self, linkinfo):
        linkinfo.register_handler(lambda url: url.netloc in ('imgur.com', 'i.imgur.com'),
                                  self._linkinfo_handler, exclusive=True)

    def _linkinfo_handler(self, url, match):
        # Split up endpoint and ID: /<image>, /a/<album> or /gallery/<id>
        kind, _, id = url.path.lstrip('/').rpartition('/')
        # Strip file extension from direct image links
        id = id.partition('.')[0]

        try:
            if kind == '':
                nsfw, title = self._format_image(self.client.get_image(id))
            elif kind == 'a':
                nsfw, title = self._format_album(self.client.get_album(id), url.fragment)
            elif kind == 'gallery':
                data = self.client.gallery_item(id)
                if data.is_album:
                    nsfw, title = self._format_album(data, None)
                else:
                    nsfw, title = self._format_image(data)
            else:
                nsfw, title = False, None
        except ImgurClientError as e:
            return LinkInfoResult(url, str(e), is_error=True)

        if title:
            return LinkInfoResult(url, title, nsfw=nsfw)
        else:
            return None

    @staticmethod
    def _format_image(data):
        title = data.title or ''
        return data.nsfw or 'nsfw' in title.lower(), title

    @staticmethod
    def _format_album(data, image_id):
        title = '{0} ({1})'.format(data.title or 'Untitled album',
                                   pluralize(data.images_count, 'image', 'images'))
        images = {i['id']: i for i in data.images}
        image = images.get(image_id)
        if image and image['title']:
            title += ': ' + image['title']
        return data.nsfw or 'nsfw' in title.lower(), title
Exemplo n.º 24
0
'''

import praw
from imgurpython import ImgurClient
from praw.models import Message
from praw.models import Comment
import random
import time
import sys

from _operator import contains
client_id = '*********'
client_secret = '*********'
client = ImgurClient(client_id, client_secret)
#items = client.gallery()
items = client.get_album('FlHzl')
#numPictures = items.__sizeof__()
reddit = praw.Reddit(client_id='*********',
                     client_secret="********",
                     password='******',
                     user_agent='eyebleachbot (by /u/su5)',
                     username='******')

messageBod = '''User: {0}

Subject: {1}


Body: {2}'''
response = '''NSFL? Yikes!
Exemplo n.º 25
0
def get_imgur_ids_from_gallery(gallery):
  return True

for post in submissions:
  sleep(1)
  #make sure it's a link
#  pprint(vars(post))
  if not post.is_self:

    if get_url_type(post.url) == "directLink":
      directUrls['directLinks'].append(post.url)

    elif get_url_type(post.url) == "imgurAlbum":
      try: 
        albumID    = get_imgur_album_id(post.url)
        if not imgurclient.get_album(albumID).title:
          albumTitle = albumID
        else:
          albumTitle = imgurclient.get_album(albumID).title.replace("/","|")
        print "scraping " + albumTitle
        imgurIDs   = get_imgur_ids_from_album(albumID)
        directUrls[albumTitle] = list()

        for imgurID in imgurIDs:
          directUrls[albumTitle].append( imgurID.link )

      except:
        pass
       
    elif get_url_type(post.url) == "imgurGallery":
      print post.url
Exemplo n.º 26
0
class imgur(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.clientID = bot.config.get('imgur_client_id')
        self.secretID = bot.config.get('imgur_client_secret')
        self.imgur_client = ImgurClient(self.clientID, self.secretID)

    @is_admin()
    @commands.command(aliases=['addalbum', 'aa'])
    async def album(self, ctx, link: str = None, *, album_name: str = None):
        """addalbum [album link] [album name] - Adds an album, link, and name.
        ex; .addalbum https://imgur.com/gallery/MnIjj3n a phone
        and 'pickone a phone' would call this album.
        """
        if not link or not album_name:
            await ctx.send(
                'Please include a link to the album and a name for the album.')
            return

        possible_links = [
            'https://imgur.com/gallery/', 'https://imgur.com/a/'
        ]  #leaving this for additions later
        if not any(x in link for x in possible_links):
            await ctx.send('That doesnt look like a valid link.')

        else:
            album_name = album_name.lower()
            fetch_albums = await self.bot.fetch.all(
                f"SELECT * FROM Albums WHERE GuildID=?", (ctx.guild.id, ))
            fetch_album_names = list([album[2] for album in fetch_albums
                                      ]) if fetch_albums else []
            if album_name not in fetch_album_names:
                await self.bot.db.execute(
                    f"INSERT INTO Albums(GuildID, AlbumName, AlbumLink) VALUES (?, ?, ?)",
                    (
                        ctx.guild.id,
                        album_name,
                        link,
                    ))
                await self.bot.db.commit()
                await ctx.send(f'"{album_name}" has been added!')
            else:
                await ctx.send(f'"{album_name}" already exists')

    @is_admin()
    @commands.command(aliases=['delalbum', 'remalbum', 'da', 'ra'])
    async def deletealbum(self, ctx, *, album_name: str = None):
        """
        deletealbum [album name] - Deletes an album, name.
        ex; .deletealbum a phone
        """
        if not album_name:
            await ctx.send('Please provide an album name.')

        if album_name:
            album_name = album_name.lower()
            fetch_album = await self.bot.fetch.one(
                f"SELECT * FROM Albums WHERE GuildID=? AND AlbumName=?",
                (ctx.guild.id, album_name))
            if fetch_album:
                await self.bot.db.execute(
                    f"DELETE FROM Albums WHERE GuildID=? And AlbumName=?", (
                        ctx.guild.id,
                        album_name,
                    ))
                await self.bot.db.commit()
                await ctx.send(f'Removed album "{album_name}"')

            else:
                await ctx.send(
                    f'Couldn\'t find an album the name of "{album_name}"')

    @commands.command(aliases=['p1', 'po', 'pick'])
    async def pickone(self, ctx, *, album_name: str = None):
        """
        pickone (Optional album name) - picks a random image from the album.
        ex; .pickone a phone
        If only one album exists you do not provide an album name.
        """
        grab_content_title_config = await self.bot.fetch.one(
            f"SELECT Content, Title FROM GuildConfig WHERE ID=?",
            (ctx.guild.id, ))
        content = grab_content_title_config[0]
        title = grab_content_title_config[1]
        if content is None and title is None:
            content = 'You asked me to pick a picture...'
            title = 'I Chose...'

        if album_name:
            album_name = album_name.lower()
            fetch_album = await self.bot.fetch.one(
                f"SELECT * FROM Albums WHERE GuildID=? AND AlbumName=?", (
                    ctx.guild.id,
                    album_name,
                ))
            if not fetch_album:
                return await ctx.send("Couldnt find an album by that name")

            if len(fetch_album) == 0:
                return await ctx.send(
                    'You should probably add an album first..')
            imgur_link = fetch_album[3]

        if not album_name:
            fetch_albums = await self.bot.fetch.all(
                f"SELECT AlbumName, AlbumLink FROM Albums WHERE GuildID=?",
                (ctx.guild.id, ))
            if not fetch_albums:
                return await ctx.send("Might want to add an album first!")

            if len(fetch_albums) >= 2:
                return await ctx.send(
                    'Seems you forgot to provide an album name!')
            imgur_link = fetch_albums[0][1]

        try:
            await ctx.message.add_reaction(
                discord.utils.get(self.bot.emojis, name='check'))
        except:
            pass

        try:
            tail = imgur_link.split('/')[4]
            the_list = list(
                item.link for item in self.imgur_client.get_album_images(tail))
            item = random.choice(the_list)
            item_id = item.split('/')[3][0:-4]
            if title in ['album title', 'Album Title']:
                title = self.imgur_client.get_album(tail).title
            if content in ['description', 'Description']:
                content = self.imgur_client.get_image(item_id).description
            if (self.imgur_client.get_image(item_id).size * 1e-6) > 8.0:
                return await ctx.send(
                    f"{self.imgur_client.get_image(item_id).link} was too big to send."
                )
            get_stream_status = await self.bot.fetch.one(
                f"SELECT Stream FROM GuildConfig WHERE ID=?", (ctx.guild.id, ))
            stream = get_stream_status[0]
            async with self.bot.aiohttp.get(item) as resp:
                link = await resp.read()
                if item.endswith('.gif'):
                    f = discord.File(io.BytesIO(link), filename="image.gif")
                    e = discord.Embed(
                        title=title,
                        colour=discord.Colour(0x278d89),
                    )
                    if stream:
                        e.set_image(url=f'''attachment://image.gif''')
                    else:
                        e.set_image(
                            url=f'{self.imgur_client.get_image(item_id).link}')
                else:
                    f = discord.File(io.BytesIO(link), filename="image.png")
                    e = discord.Embed(
                        title=title,
                        colour=discord.Colour(0x278d89),
                    )
                    if stream:
                        e.set_image(url=f'''attachment://image.png''')
                    else:
                        e.set_image(
                            url=f'{self.imgur_client.get_image(item_id).link}')

                e.set_footer(
                    text=
                    f'storage is currently: {"link" if not stream else "stream"} \n'
                    f'if images aren\'t showing up, try toggling this with .stream'
                )
                if stream:
                    await ctx.send(file=f, embed=e, content=content)

                if not stream:
                    await ctx.send(embed=e, content=content)

        except Exception as e:
            print(
                f'{e}, tail: {tail if tail else None} link: {imgur_link}, item: {item if item else None}'
            )
            if isinstance(e, ImgurClientError):
                print(f'{e.error_message}')
                return await ctx.send(f'{e.error_message}')
            elif not isinstance(e, ImgurClientError):
                return await ctx.send(
                    f'There was an issue processing this command.\nDebug: `{e}`'
                )

    @commands.command(aliases=['al', 'list'])
    async def albumlist(self, ctx):
        """albumlist - displays all currently added albums by name.

        """
        fetch_albums = await self.bot.fetch.all(
            f"SELECT * FROM Albums WHERE GuildID=?", (ctx.guild.id, ))
        if fetch_albums:
            list_album_names = ", ".join(
                list([album[2] for album in fetch_albums]))
            await ctx.send(f"{list_album_names}")
        else:
            await ctx.send('It doesnt seem that you have added an ablum.')

    @is_admin()
    @commands.command(aliases=['adda', 'admin'])
    async def addadmin(self, ctx, member: discord.Member = None):
        """addadmin [user name] - Adds an admin
        ex; .addadmin @ProbsJustin#0001
        You can attempt to use just a string name; eg ProbsJustin but recommend a mention.
        """
        if not member:
            await ctx.send('You should probably include a member.')
            return

        else:
            check_if_pwr_user = await self.bot.fetch.one(
                f"SELECT * FROM Permissions WHERE MemberID=? AND GuildID=?", (
                    ctx.author.id,
                    ctx.guild.id,
                ))
            if not check_if_pwr_user:
                await self.bot.db.execute(
                    f"INSERT INTO Permissions(MemberID, GuildID) VALUES (?, ?)",
                    (
                        ctx.author.id,
                        ctx.guild.id,
                    ))
                await self.bot.db.commit()
                await ctx.send(f'{member.mention} has been added as an admin.')
            else:
                await ctx.send('That user is already an admin!')

    @is_admin()
    @commands.command(aliases=['remadmin', 'deladmin', 'deleteadmin'])
    async def removeadmin(self, ctx, member: discord.Member = None):
        """removeadmin [user name] - Remove an admin
        ex; .removeadmin @ProbsJustin#0001
        You can attempt to use just a string name; eg ProbsJustin but recommend a mention.
        """
        if not member:
            await ctx.send('You should probably include a member.')
            return
        else:
            chck_if_usr_is_admin = await self.bot.fetch.one(
                f"SELECT * FROM Permissions WHERE MemberID=? AND GuildID=?", (
                    ctx.author.id,
                    ctx.guild.id,
                ))
            if chck_if_usr_is_admin:
                await self.bot.db.execute(
                    f"DELETE FROM Permissions WHERE MemberID=? AND GuildID=?",
                    (
                        ctx.author.id,
                        ctx.guild.id,
                    ))
                await self.bot.db.commit()
                await ctx.send(
                    f'{member.mention} has been removed as an admin.')
            else:
                await ctx.send('I couldnt find that user in the admin list.')

    @addadmin.error
    @removeadmin.error
    async def member_not_found_error(self, ctx,
                                     exception):  #so this is a thing.
        if not isinstance(exception, NotAuthorized):
            await ctx.send('Member not found! Try mentioning them instead.')

    @is_admin()
    @commands.command()
    async def set(self, ctx, content_title: str = None, *, message: str = ''):
        """set [content/title] [name] - Change the title/content from "I Chose..." "you asked.." """
        editable_args = ['content', 'title']
        if not content_title:
            await ctx.send(
                f"Please provide either {' or '.join(editable_args)}.")
            return
        content_title = content_title.lower()
        if content_title in editable_args:
            if content_title == "title":
                await self.bot.db.execute(
                    f"UPDATE GuildConfig SET Title=? WHERE ID=?", (
                        message,
                        ctx.guild.id,
                    ))
            if content_title == 'content':
                await self.bot.db.execute(
                    f"UPDATE GuildConfig SET Content=? WHERE ID=?", (
                        message,
                        ctx.guild.id,
                    ))

            await self.bot.db.commit()
            await ctx.send(f'{content_title.lower()} updated.')

        else:
            await ctx.send("Invalid parameters.")

    @is_admin()
    @commands.command()
    async def stream(self, ctx):
        """
        Toggles how the images are sent to discord, if images aren't showing up try toggling this.
        """
        get_stream_status = await self.bot.fetch.one(
            f"SELECT Stream FROM GuildConfig WHERE ID=?", (ctx.guild.id, ))
        update_stream_status = await self.bot.db.execute(
            f"UPDATE GuildConfig SET Stream=? WHERE ID=?",
            (not get_stream_status[0], ctx.guild.id))
        await self.bot.db.commit()
        await ctx.send(
            f"Streaming turned {'on' if not get_stream_status[0] else 'off'}")
Exemplo n.º 27
0
u = urllib.URLopener()

srcreddits = ('Pics', 'EarthPorn', 'LavaPorn', 'AbandonedPorn', 'SpacePorn')

for sub in srcreddits:
    print "Getting Most Recent Images From Subreddit: r/" + sub
    imgs += imgur.subreddit_gallery(sub, sort='time', window='day', page=0)

for img in imgs:

    # If an album according to API only cover img available when accessed as gallery
    # Use API get_album method to grab all the images in the album

    if img.is_album == True:
        print "Getting album " + img.id
        i = imgur.get_album(img.id)

        for pix in i.images:

            filename = pix['link'].split('/')[-1]

            #print "Album branch, pix['link'] is " + pix['link'] + " file is " + file

            if int(pix['width']) > int(pix['height']):

                if os.path.isfile('/home/pi/Pictures/' + filename):
                    print "Album Branch - File already exists"
                else:
                    print "Downloading album image " + pix[
                        'link'] + " to file " + filename
                    u.retrieve(pix['link'], "/home/pi/Pictures/" + filename)
Exemplo n.º 28
0
class Bot:

    def __init__(self,  videobot, slave_bot):
        """
        Initializes the Imgur Bot with credentials stored in environment variables.
        :return: ImgurClient object
        """
        IMGUR_CLIENT_ID = os.environ.get("IMGUR_CLIENT_ID")
        IMGUR_CLIENT_SECRET = os.environ.get("IMGUR_CLIENT_SECRET")
        self.client = ImgurClient(IMGUR_CLIENT_ID, IMGUR_CLIENT_SECRET)
        self.supported_video_formats = ['gif','gifv', 'webm', 'mp4']
        self.slave_bot = slave_bot
        self.video_bot = videobot

    def handle_album(self, album_link):

        """
        handles imgur links of the format: imgur.com/a/<id>, imgur.com/<id>#<img id>
        :type album_link: 'str'
        :rtype message: 'str' - Analysis message from Bot.
        :rtype status: <Dict> - {'nsfw':<float>, 'sfw':<float>}
        """
        temp = album_link.split('/')[-1]
        album_id = temp.split('#')[0]

        message = None
        status = {}

        try:
            album = self.client.get_album(album_id=album_id)

            imgur_flag = album.nsfw


            if imgur_flag:
                message = 'Album marked NSFW on Imgur.'
                message = '**[Hover to reveal](#s "' + message + '")**'  # reddit spoiler tag added.

            elif not imgur_flag:

                images_list = self.client.get_album_images(album_id)

                links = [item.link for item in images_list[0:10]
                         if item.type.split('/')[-1] not in self.supported_video_formats]
                links_videos = [item.link for item in images_list[0:10]
                                if item.type.split('/')[-1] in self.supported_video_formats]
                # Ensures only 10 images/gifs are processed in case album is very large.

                temp1, _ = self.handle_videos(links_videos)
                temp2, _ = self.handle_images(links)

                status.update(temp1)
                status.update(temp2)

                # for all images, if SFW - mark SFW.
                # if any image is not SFW, find out which one.

                max_nsfw= (None, 0)
                min_sfw = (None, 100)
                for k,v in status.items():
                    labels = sorted(status[k].items(), key=operator.itemgetter(1), reverse=True)

                    tag, confidence = labels[0]

                    if tag is 'SFW' and confidence<=min_sfw[1]:
                        min_sfw = labels[0]

                    elif tag is not 'SFW' and confidence>max_nsfw[1]:
                        max_nsfw = labels[0]


                if max_nsfw != (None, 0):
                    message = "Album has "+str(max_nsfw[0])+" image(s). I'm {0:.2f}% confident.".format(max_nsfw[1])

                elif max_nsfw == (None, 0):

                    message = "Album has "+str(min_sfw[0])+" image(s). I'm {0:.2f}% confident.".format(min_sfw[1])


                message = '**[Hover to reveal](#s "'+message+' ")**'  #reddit spoiler tag added.

        except error.ImgurClientError as e:
            status = None
            message = None
            print ('Imgur Error:', e.error_message)

        return status, message

    def handle_images(self, links):
        status = {}
        message = None

        valid_links = [self.ensure_extension(aLink) for aLink in links
                       if aLink.split('.')[-1].lower() not in ['gif', 'gifv', 'mp4', 'webm']]

        status = self.slave_bot.analyze(valid_links)

        if len(valid_links) == 1:
            link = valid_links[0]
            labels = sorted(status[link].items(), key=operator.itemgetter(1), reverse=True)
            tag, confidence = labels[0]
            message = tag + ". I'm  {0:.2f}% confident.".format(confidence)
            if tag is 'SFW':
                manning_distance = self.slave_bot.clarifai_bot.match_template(link, 'manning')
                if manning_distance is not None and manning_distance <= 0.01:
                    message += ' Might be Manning Face.'

            message = '**[Hover to reveal](#s "' + message + ' ")**'  # reddit spoiler tag added.

        return status, message

    def handle_gallery(self, gallery_link):
        item_id = gallery_link.split('/')[-1]
        # user linked to either an album or an image from the imgur gallery.
        # assume it is album. if it's a 404, assume it is an image.

        message = ''
        status = {}

        try:
            album = self.client.get_album(album_id=item_id)

            imgur_flag = album.nsfw

            if imgur_flag:
                status = {}
                message = 'Album marked NSFW on Imgur.'
                message = '**[Hover to reveal](#s "' + message + '")**'  # reddit spoiler tag added.

            elif not imgur_flag:
                status, message = self.handle_album(album.link)

        except error.ImgurClientError as e:
            try:
                image = self.client.get_image(item_id)
                imgur_flag = image.nsfw

                if imgur_flag:
                    message = 'Item marked NSFW on Imgur.'
                    message = '**[Hover to reveal](#s "' + message + '")**'  # reddit spoiler tag added.

                elif not imgur_flag:

                    if image.type.split('/')[-1] in self.supported_video_formats:
                        status, message = self.handle_videos([image.link])
                    else:
                        status, message = self.handle_images([image.link])

            except error.ImgurClientError as e:
                status = None
                message = None
                print('Imgur Error', e.error_message)

        return status, message

    def handle_videos(self, links):
        status = {}
        message = None
        for each_url in links:
            link = self.ensure_extension(each_url)

            # link is now 'imgur.com/id.extension'
            video_id = link.split('/')[-1].split('.')[0]
            filename = video_id+'.mp4'
            mp4_link = 'http://i.imgur.com/'+filename
            urllib.urlretrieve(mp4_link, filename)
            status.update({each_url:self.video_bot.make_prediction(filename)})

            if os.path.exists(filename):
                os.remove(filename)

        if len(links) == 1:
            link = links[0]
            labels = sorted(status[link].items(), key=operator.itemgetter(1), reverse=True)
            tag, confidence = labels[0]
            message = tag + ". I'm  {0:.2f}% confident.".format(confidence)
            message = '**[Hover to reveal](#s "' + message + ' ")**'  # reddit spoiler tag added.

        return status, message

    def ensure_extension(self, url):
        temp = url.split('/')[-1]  # will be <image_id>.<extension> or <image_id>
        if '.' not in temp:
            image_id = temp

            url = self.client.get_image(image_id).link
            return url
        else:
            return url
Exemplo n.º 29
0
if sys.version_info[0]== 2:
    pass 
elif sys.version_info[0] == 3:
    from builtins import input

# trying to fix the error messages
import urllib3
urllib3.disable_warnings()

parser = argparse.ArgumentParser(description='imgur2pdf - convert an imgur gallery to pdf for archival purposes')
parser.add_argument('album', metavar='album',  help='id of imgur album')
parser.add_argument('destination', metavar='destination', help='location to save to')
args = parser.parse_args()

client = ImgurClient(client_id, client_secret)
album_data = client.get_album(args.album)
album_file = album_data.title.replace(' ','_')+".pdf"

path = args.destination[:-1] + '/' + album_file

if os.path.isfile(path) == True:
    # we found something!
    print("found file %s, try with another destination" % path)
    quit()
else:
    # nothing found, lets make stuff
    pass


doc = SimpleDocTemplate(path,pagesize=letter,
                        rightMargin=25,leftMargin=25,
Exemplo n.º 30
0
def get_url(submission, mp4_instead_gif=True):
    '''
    return TYPE, URL, EXTENSION
    E.x.: return 'img', 'http://example.com/pic.png', 'png'
    '''
    def what_is_inside(url):
        header = requests.head(url).headers
        if 'Content-Type' in header:
            return header['Content-Type']
        else:
            return ''

    url = submission.url
    url_content = what_is_inside(url)

    if (CONTENT_JPEG == url_content or CONTENT_PNG == url_content):
        return TYPE_IMG, url, url_content.split('/')[1]

    if CONTENT_GIF in url_content:
        if url.endswith('.gif') and mp4_instead_gif:
            # Let's try to find .mp4 file.
            url_mp4 = url[:-4] + '.mp4'
            if CONTENT_MP4 == what_is_inside(url_mp4):
                return TYPE_GIF, url_mp4, 'mp4'
        return TYPE_GIF, url, 'gif'

    if url.endswith('.gifv'):
        if mp4_instead_gif:
            url_mp4 = url[:-5] + '.mp4'
            if CONTENT_MP4 == what_is_inside(url_mp4):
                return TYPE_GIF, url_mp4, 'mp4'
        if CONTENT_GIF in what_is_inside(url[0:-1]):
            return TYPE_GIF, url[0:-1], 'gif'

    if submission.is_self is True:
        # Self submission with text
        return 'text', None, None

    if urlparse(url).netloc == 'imgur.com':
        # Imgur
        imgur_config = yaml.load(open('imgur.yml').read())
        imgur_client = ImgurClient(imgur_config['client_id'],
                                   imgur_config['client_secret'])
        path_parts = urlparse(url).path.split('/')
        if path_parts[1] == 'gallery':
            # TODO: gallary handling
            return 'other', url, None
        elif path_parts[1] == 'topic':
            # TODO: topic handling
            return 'other', url, None
        elif path_parts[1] == 'a':
            # An imgur album
            album = imgur_client.get_album(path_parts[2])
            story = {}
            for num, img in enumerate(album.images):
                number = num + 1
                what = TYPE_IMG
                link = img['link']
                ext = img['type'].split('/')[1]
                if img['animated']:
                    what = TYPE_GIF
                    link = img['mp4'] if mp4_instead_gif else img['gifv'][:-1]
                    ext = 'mp4' if mp4_instead_gif else 'gif'
                story[number] = {'url': link, 'what': what, 'ext': ext}
            return 'album', story, None
        else:
            # Just imgur img
            img = imgur_client.get_image(path_parts[1].split('.')[0])
            if not img.animated:
                return TYPE_IMG, img.link, img.type.split('/')[1]
            else:
                if mp4_instead_gif:
                    return TYPE_GIF, img.mp4, 'mp4'
                else:
                    # return 'gif', img.link, 'gif'
                    return TYPE_GIF, img.gifv[:-1], 'gif'
    else:
        return 'other', url, None
Exemplo n.º 31
0
# TODO: add metrics downloaded x images in x {min or sec}

q = Queue.Queue(maxsize=0)
# Change the number of simultaneous threads
num_threads = 10

client_id = ''
client_secret = ''

client = ImgurClient(client_id, client_secret)
gallery_url = raw_input('Enter gallery URL: ').split('/')[-1]

try:
    gallery = client.gallery_item(gallery_url)
except(imgurpython.helpers.error.ImgurClientError):
    gallery = client.get_album(gallery_url)

download_path = os.path.join('c:', os.environ['HOMEPATH'], 'Downloads')

os.chdir(download_path)

if isinstance(gallery.title, unicode) is False:
    print 'has no title'
    gallery.title = gallery.id
else:
    gallery.title = str(gallery.title).translate(None, string.punctuation)


print(gallery.title)
os.mkdir(gallery.title)
os.chdir(gallery.title)
Exemplo n.º 32
0
from imgurpython import ImgurClient
import BotIDs
import re

album = "http://imgur.com/a/ES0Zc"
albumID = re.findall(r"imgur.com/a/(\w+)", album)[0]

client = ImgurClient(BotIDs.imgur_clientID, BotIDs.imgur_Secret)

albumObj = client.get_album(albumID)
albumPics = client.get_album_images(albumID)

stickers = {}

for pic in albumPics:
    stickers[pic.description] = pic.link
Exemplo n.º 33
0

def zipdir(path, ziph):
    for root, dirs, files in os.walk(path):
        for file in files:
            ziph.write(os.path.join(root, file))


album_id = sys.argv[1]

client_id = 'a17235ad4b51446'
client_secret = '66b1c6fc9c7ffd4b665ea7ba9cb6beb67a4d47c7'

client = ImgurClient(client_id, client_secret)

album = client.get_album(album_id)

album_dir = '%s - %s' % (album.id, album.title)
os.mkdir(album_dir)

seq = 0
for image in album.images:
    seq += 1
    therest, filename = image['link'].rsplit('/', 1)
    filename, extension = filename.rsplit('.', 1)
    urllib.request.urlretrieve(image['link'],
                               "%s/%04d.%s" % (album_dir, seq, extension))
    print(("%0" + str(len(str(len(album.images)))) + "d/%d") %
          (seq, len(album.images)), image['link'])

zipf = zipfile.ZipFile("%s.cbz" % album_dir, 'w', zipfile.ZIP_STORED)
Exemplo n.º 34
0
class imgur(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.clientID = bot.config.data.get('config').get('imgur_client_id')
        self.secretID = bot.config.data.get('config').get(
            'imgur_client_secret')
        self.imgur_client = ImgurClient(self.clientID, self.secretID)

    async def fetch_one(self, arg):
        get = await self.bot.db.execute(arg)
        results = await get.fetchone()
        return results

    async def fetch_all(self, arg):
        get = await self.bot.db.execute(arg)
        results = await get.fetchall()
        return results

    @is_admin()
    @commands.command(aliases=['addalbum', 'aa'])
    async def album(self, ctx, link: str = None, *, album_name: str = None):
        """addalbum [album link] [album name] - Adds an album, link, and name.
        ex; .addalbum https://imgur.com/gallery/MnIjj3n a phone
        and 'pickone a phone' would call this album.
        """
        if not link or not album_name:
            await ctx.send(
                'Please include a link to the album and a name for the album.')
            return

        possible_links = [
            'https://imgur.com/gallery/', 'https://imgur.com/a/'
        ]  #leaving this for additions later
        if not any(x in link for x in possible_links):
            await ctx.send('That doesnt look like a valid link.')

        else:
            album_name = album_name.lower()
            get_albums = await imgur.fetch_all(
                self,
                f'SELECT AlbumLink FROM GuildAlbums WHERE GuildID={ctx.guild.id}'
            )
            if link not in list(albumlink[0] for albumlink in get_albums):
                await self.bot.db.execute(
                    f"INSERT INTO GuildAlbums(GuildID, AlbumLink, AlbumName) "
                    f"VALUES (?, ?, ?)", (ctx.guild.id, link, album_name))
                await self.bot.db.commit()
                await ctx.send(f'"{album_name}" has been added!')
            else:
                albums_name = await imgur.fetch_one(
                    self,
                    f'SELECT AlbumName FROM GuildAlbums WHERE AlbumLink="{link}"'
                )
                await ctx.send(f'{link} already exists as {albums_name[0]}.')

    @is_admin()
    @commands.command(aliases=['delalbum', 'remalbum', 'da', 'ra'])
    async def deletealbum(self, ctx, *, album_name: str = None):
        """deletealbum [album name] - Deletes an album, name.
        ex; .deletealbum a phone
        """
        if not album_name:
            await ctx.send('Please provide an album name.')
        get_albums = await imgur.fetch_all(
            self,
            f'SELECT AlbumName FROM GuildAlbums WHERE GuildID={ctx.guild.id}')
        if album_name.lower() in list(albumnames[0]
                                      for albumnames in get_albums):
            await self.bot.db.execute(
                f'DELETE FROM GuildAlbums WHERE GuildID=? and AlbumName=?',
                (ctx.guild.id, album_name.lower()))
            await self.bot.db.commit()
            await ctx.send(f'Removed album "{album_name}"')

        else:
            await ctx.send(f'Couldnt find an album the name of "{album_name}"')

    @commands.command(aliases=['p1', 'po', 'pick'])
    async def pickone(self, ctx, *, album_name: str = None):
        """pickone (Optional album name) - picks a random image from the album.
        ex; .pickone a phone
        If only one album exists you do not provide an album name.
        """
        album_names = await imgur.fetch_all(
            self,
            f'SELECT AlbumName FROM GuildAlbums WHERE GuildID={ctx.guild.id}')
        if not album_names:
            await ctx.send('You should probably add an album first..')
            return

        content = await imgur.fetch_one(
            self, f'SELECT Content FROM GuildConfig WHERE ID={ctx.guild.id}')
        title = await imgur.fetch_one(
            self, f'SELECT Title FROM GuildConfig WHERE ID={ctx.guild.id}')
        await ctx.message.add_reaction(
            discord.utils.get(self.bot.emojis, name='check'))
        content = 'You asked me to pick a picture...' if not content[
            0] else content[0]
        title = 'I Chose...' if not title[0] else title[0]
        if album_name:
            if album_name.lower() in list(albumnames[0]
                                          for albumnames in album_names):
                album_link = await imgur.fetch_one(
                    self, f'SELECT AlbumLink FROM GuildAlbums WHERE '
                    f'AlbumName="{album_name.lower()}" and GuildID={ctx.guild.id}'
                )
                tail = album_link[0].split('/')[4]
                the_list = list(
                    item.link
                    for item in self.imgur_client.get_album_images(tail))
            else:
                await ctx.send(
                    f'I couldnt find an album by the name of "{album_name}"')

        if not album_name:
            if len(album_names) >= 2:
                await ctx.send('Seems you forgot to provide an album name!')
                return
            if len(album_names) == 1:
                album_link = await imgur.fetch_one(
                    self, f'SELECT AlbumLink FROM GuildAlbums WHERE '
                    f'AlbumName="{album_names[0][0]}" and GuildID={ctx.guild.id}'
                )
                tail = album_link[0].split('/')[4]
                the_list = list(
                    item.link
                    for item in self.imgur_client.get_album_images(tail))
        try:
            item = random.choice(the_list)
            item_id = item.split('/')[3][0:-4]
            if title in ['album title', 'Album Title']:
                title = self.imgur_client.get_album(tail).title
            if content in ['description', 'Description']:
                content = self.imgur_client.get_image(item_id).description
            async with self.bot.aiohttp.get(item) as resp:
                link = await resp.read()
                if item.endswith('.gif'):
                    f = discord.File(io.BytesIO(link), filename="image.gif")
                    e = discord.Embed(title=title,
                                      colour=discord.Colour(0x278d89))
                    e.set_image(url=f'''attachment://image.gif''')
                else:
                    f = discord.File(io.BytesIO(link), filename="image.png")
                    e = discord.Embed(title=title,
                                      colour=discord.Colour(0x278d89))
                    e.set_image(url=f'''attachment://image.png''')
                await ctx.send(file=f, embed=e, content=content)

        except Exception as e:
            if isinstance(e, ImgurClientError):
                print(f'{e.error_message}')
                await ctx.send(f'{e.error_message}')
            elif not isinstance(e, ImgurClientError):
                await ctx.send(
                    f'There was an issue processing this command. {e}')

    @commands.command(aliases=['al', 'list'])
    async def albumlist(self, ctx):
        """albumlist - displays all currently added albums by name.
        """
        album_names = await imgur.fetch_all(
            self,
            f'SELECT AlbumName FROM GuildAlbums WHERE GuildID={ctx.guild.id}')
        if len(album_names) is not 0:
            await ctx.send(
                f"The list of albums I see are: {', '.join(list(an[0] for an in album_names))}."
            )
        else:
            await ctx.send('It doesnt seem that you have added an ablum.')

    @is_admin()
    @commands.command(aliases=['adda', 'admin'])
    async def addadmin(self, ctx, member: discord.Member = None):
        """addadmin [user name] - Adds an admin
        ex; .addadmin @ProbsJustin#0001
        You can attempt to use just a string name; eg ProbsJustin but recommend a mention.
        """
        if not member:
            await ctx.send('You should probably include a member.')
            return
        else:
            get_admins = await imgur.fetch_all(
                self,
                f'SELECT AdminID FROM GuildAdmins WHERE GuildID={ctx.guild.id}'
            )
            if member.id not in list(admin[0] for admin in get_admins):
                await self.bot.db.execute(
                    f"INSERT INTO GuildAdmins(GuildID, AdminID) VALUES (?, ?)",
                    (ctx.guild.id, member.id))
                await self.bot.db.commit()
                await ctx.send(f'{member.mention} has been added as an admin.')
            else:
                await ctx.send('That user is already an admin!')

    @is_admin()
    @commands.command(aliases=['remadmin', 'deladmin', 'deleteadmin'])
    async def removeadmin(self, ctx, member: discord.Member = None):
        """removeadmin [user name] - Remove an admin
        ex; .removeadmin @ProbsJustin#0001
        You can attempt to use just a string name; eg ProbsJustin but recommend a mention.
        """
        if not member:
            await ctx.send('You should probably include a member.')
            return
        else:
            get_admins = await imgur.fetch_all(
                self,
                f'SELECT AdminID FROM GuildAdmins WHERE GuildID={ctx.guild.id}'
            )
            if member.id in list(admin[0] for admin in get_admins):
                await self.bot.db.execute(
                    f'DELETE FROM GuildAdmins WHERE GuildID=? and AdminID=?',
                    (ctx.guild.id, member.id))
                await self.bot.db.commit()
                await ctx.send(
                    f'{member.mention} has been removed as an admin.')
            else:
                await ctx.send('I couldnt find that user in the admin list.')

    @addadmin.error
    @removeadmin.error
    async def member_not_found_error(self, ctx,
                                     exception):  #so this is a thing.
        if not isinstance(exception, NotAuthorized):
            await ctx.send('Member not found! Try mentioning them instead.')

    @is_admin()
    @commands.command()
    async def set(self, ctx, content_title: str = None, *, message: str = ''):
        """set [content/title] [name] - Change the title/content from "I Chose..." "you asked.." """
        editable_args = ['content', 'title']
        if not content_title:
            await ctx.send(
                f"Please provide either {' or '.join(editable_args)}.")
            return

        if content_title.lower() in editable_args:
            await self.bot.db.execute(
                f'UPDATE GuildConfig SET {content_title.title()}="{message}" '
                f'WHERE ID={ctx.guild.id}')
            await self.bot.db.commit()
            await ctx.send(f'{content_title.lower()} updated.')

        else:
            await ctx.send("Invalid parameters.")
Exemplo n.º 35
0
 def execute(self, subreddit, BANNER, LIMIT):
     global r
     client = ImgurClient(cfg_file.get('imgur', 'client_id'), cfg_file.get('imgur', 'client_secret'))
     album_id = get_album_id(self.url)
     album = client.get_album(album_id)
     album_title = self.title
     album = album.images
     COUNT = len(album)
     if COUNT < LIMIT:
         print('Not enough images!')
         send_error_message(cfg_file.get('reddit', 'owner_username'), subreddit.display_name,   'Not enough '
                            ' images in album ["{0}"]({1})'.format(album_title, self.url))
         return
  
     # Pick x random ones if greater than limit
     if COUNT > LIMIT:
         album = random.sample(album, COUNT)
     banner_number = 0
     sidebar_format = '* [{title}]({link} "{desc}")'
     sidebar_lines = []
     bigpic = []
     for image in album:
         if image['size'] > 512000:
             print ('too big: %s' %(image['link']))
             title = '{0} - ({1} kB) -  {2}px x {3}px'.format(image['link'], float(image['size'])/1000, image['width'], image['height'])
             bigpic.append(sidebar_format.format(title=title, link=image['link'], desc=image['description']))
             continue
         banner_number += 1
         url = image['link']
         local_name = localize_name(album_id, url)
         download_image(url, local_name)
        
         title = image['title'] if image['title'] else 'Untitled'
         description = image['description'] if image['description'] else ' '
         line = sidebar_format.format(title=title, link='#s', desc=description)
         
          
         css_name = BANNER + '%d' % banner_number
         print('%s: adding %s to stylesheet...' % (subreddit, css_name))
         try:
             r.upload_image(subreddit, local_name, css_name)
         except Exception as e:
             print (e)
             return
         sidebar_lines.append(line)
         if banner_number >= LIMIT:
             break
     if banner_number < LIMIT:
         print ('Not enough valid images')
         send_error_message(cfg_file.get('reddit', 'owner_username'), subreddit.display_name,   'Not enough valid'
                            ' images in album ["{0}"]({1}); check that the following image sizes are less than 500kB. '
                            'Images ideally should be greater than 300px wide and 1:1 or greater aspect ratio: \n\n{2}'.format(album_title, self.url, '\n'.join(bigpic)))
         return
     bar = '\n'.join(sidebar_lines)
     bar = '##### ' + album_title + '\n' + bar + '\n\n'
     r.config.decode_html_entities = True
     current_sidebar = subreddit.get_settings()['description']
     current_sidebar = HTMLParser.HTMLParser().unescape(current_sidebar)
     replace_pattern = re.compile('%s.*?%s' % (re.escape(cfg_file.get('reddit', 'start_delimiter')), re.escape(cfg_file.get('reddit', 'end_delimiter'))), re.IGNORECASE|re.DOTALL|re.UNICODE)
     new_sidebar = re.sub(replace_pattern,
                         '%s\\n\\n%s\\n%s' % (cfg_file.get('reddit', 'start_delimiter'), bar, cfg_file.get('reddit', 'end_delimiter')),
                         current_sidebar)
     
     
     r.update_settings(subreddit, description=new_sidebar)
     print ('%s sidebar updated!' %subreddit)
     subreddit.set_stylesheet(subreddit.get_stylesheet()['stylesheet'])
     print ('%s stylesheet set!' %subreddit)
     if bigpic:
         send_error_message(cfg_file.get('reddit', 'owner_username'), subreddit.display_name,   'The following '
                            ' images in album ["{0}"]({1}) were not valid and were skipped; check that the following image sizes are less than 500kB. '
                            'Images ideally should be greater than 300px wide and 1:1 or greater aspect ratio: \n\n{2}'.format(album_title, self.url, '\n'.join(bigpic)))
Exemplo n.º 36
0
import os
from imgurpython import ImgurClient
from urllib import urlretrieve

client_id = os.environ['IMGUR_ID']
client_secret = os.environ['IMGUR_SECRET']

client = ImgurClient(client_id, client_secret)

imgURL = sys.argv[1]
imgID = ''

if 'imgur.com/a/' in imgURL:
    match = re.search(r'(imgur.com/a/)(\w+)', imgURL)

    info = client.get_album(match.group(2))
    imgURL = 'http://i.imgur.com/' + info.cover + 'l.jpg'
    imgID = info.cover
elif 'imgur.com/gallery' in imgURL:
    match = re.search(r'(imgur.com/gallery/)(\w+)', imgURL)

    try:
        info = client.get_album(match.group(2))
        imgURL = 'http://i.imgur.com/' + info.cover + 'l.jpg'
        imgID = info.cover
    except:
        imgURL = 'http://i.imgur.com/' + match.group(2) + 'l.jpg'
        imgID = match.group(2)
elif 'imgur.com/r/' in imgURL:
    match = re.search(r'(imgur.com/r/\w+/)(\w+)', imgURL)
Exemplo n.º 37
0
def get_url(submission, mp4_instead_gif=True):
    '''
    return TYPE, URL, EXTENSION
    E.x.: return 'img', 'http://example.com/pic.png', 'png'
    '''
    
    def what_is_inside(url):
        header = requests.head(url).headers
        if 'Content-Type' in header:
            return header['Content-Type']
        else:
            return ''

    url = submission.url
    url_content = what_is_inside(url)

    if (CONTENT_JPEG == url_content or CONTENT_PNG == url_content):
        return TYPE_IMG, url, url_content.split('/')[1]

    if CONTENT_GIF in url_content:
        if url.endswith('.gif') and mp4_instead_gif:
            # Let's try to find .mp4 file.
            url_mp4 = url[:-4] + '.mp4'
            if CONTENT_MP4 == what_is_inside(url_mp4):
                return TYPE_GIF, url_mp4, 'mp4'
        return TYPE_GIF, url, 'gif'
    
    if url.endswith('.gifv'):
        if mp4_instead_gif:
            url_mp4 = url[:-5] + '.mp4'
            if CONTENT_MP4 == what_is_inside(url_mp4):
                return TYPE_GIF, url_mp4, 'mp4'
        if CONTENT_GIF in what_is_inside(url[0:-1]):
            return TYPE_GIF, url[0:-1], 'gif'

    if submission.is_self is True:
        # Self submission with text
        return TYPE_TEXT, None, None

    if urlparse(url).netloc == 'imgur.com':
        # Imgur
        imgur_config = yaml.load(open(os.path.join('configs', 'imgur.yml')).read())
        imgur_client = ImgurClient(imgur_config['client_id'], imgur_config['client_secret'])
        path_parts = urlparse(url).path.split('/')
        if path_parts[1] == 'gallery':
            # TODO: gallary handling
            return TYPE_OTHER, url, None
        elif path_parts[1] == 'topic':
            # TODO: topic handling
            return TYPE_OTHER, url, None
        elif path_parts[1] == 'a':
            # An imgur album
            album = imgur_client.get_album(path_parts[2])
            story = dict()
            for num, img in enumerate(album.images):
                number = num + 1
                what = TYPE_IMG
                link = img['link']
                ext = img['type'].split('/')[1]
                if img['animated']:
                    what = TYPE_GIF
                    link = img['mp4'] if mp4_instead_gif else img['gifv'][:-1]
                    ext = 'mp4' if mp4_instead_gif else 'gif'
                story[number] = {
                    'url': link,
                    'what': what,
                    'ext': ext
                }
            if len(story) == 1:
                return story[1]['what'], story[1]['url'], story[1]['ext']
            return TYPE_ALBUM, story, None
        else:
            # Just imgur img
            img = imgur_client.get_image(path_parts[1].split('.')[0])
            if not img.animated:
                return TYPE_IMG, img.link, img.type.split('/')[1]
            else:
                if mp4_instead_gif:
                    return TYPE_GIF, img.mp4, 'mp4'
                else:
                    # return 'gif', img.link, 'gif'
                    return TYPE_GIF, img.gifv[:-1], 'gif'
    elif 'gfycat.com' in urlparse(url).netloc:
        client = GfycatClient()
        rname = re.findall(r'gfycat.com\/(?:detail\/)?(\w*)', url)[0]
        try:
            urls = client.query_gfy(rname)['gfyItem']
            if mp4_instead_gif:
                return TYPE_GIF, urls['mp4Url'], 'mp4'
            else:
                return TYPE_GIF, urls['max5mbGif'], 'gif'
        except KeyError:
            logging.info('Gfy fail prevented!')
            return TYPE_OTHER, url, None
    else:
        return TYPE_OTHER, url, None
Exemplo n.º 38
0
    return True


for post in submissions:
    sleep(1)
    #make sure it's a link
    #  pprint(vars(post))
    if not post.is_self:

        if get_url_type(post.url) == "directLink":
            directUrls['directLinks'].append(post.url)

        elif get_url_type(post.url) == "imgurAlbum":
            try:
                albumID = get_imgur_album_id(post.url)
                if not imgurclient.get_album(albumID).title:
                    albumTitle = albumID
                else:
                    albumTitle = imgurclient.get_album(albumID).title.replace(
                        "/", "|")
                print "scraping " + albumTitle
                imgurIDs = get_imgur_ids_from_album(albumID)
                directUrls[albumTitle] = list()

                for imgurID in imgurIDs:
                    directUrls[albumTitle].append(imgurID.link)

            except:
                pass

        elif get_url_type(post.url) == "imgurGallery":