├── docs ├── .nojekyll ├── erm.mwb ├── html │ ├── objects.inv │ ├── _static │ │ ├── up.png │ │ ├── down.png │ │ ├── file.png │ │ ├── minus.png │ │ ├── plus.png │ │ ├── comment.png │ │ ├── up-pressed.png │ │ ├── ajax-loader.gif │ │ ├── comment-close.png │ │ ├── down-pressed.png │ │ ├── comment-bright.png │ │ ├── fonts │ │ │ ├── Lato │ │ │ │ ├── lato-bold.eot │ │ │ │ ├── lato-bold.ttf │ │ │ │ ├── lato-bold.woff │ │ │ │ ├── lato-bold.woff2 │ │ │ │ ├── lato-italic.eot │ │ │ │ ├── lato-italic.ttf │ │ │ │ ├── lato-italic.woff │ │ │ │ ├── lato-regular.eot │ │ │ │ ├── lato-regular.ttf │ │ │ │ ├── lato-italic.woff2 │ │ │ │ ├── lato-regular.woff │ │ │ │ ├── lato-regular.woff2 │ │ │ │ ├── lato-bolditalic.eot │ │ │ │ ├── lato-bolditalic.ttf │ │ │ │ ├── lato-bolditalic.woff │ │ │ │ └── lato-bolditalic.woff2 │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ ├── fontawesome-webfont.woff2 │ │ │ └── RobotoSlab │ │ │ │ ├── roboto-slab-v7-bold.eot │ │ │ │ ├── roboto-slab-v7-bold.ttf │ │ │ │ ├── roboto-slab-v7-bold.woff │ │ │ │ ├── roboto-slab-v7-bold.woff2 │ │ │ │ ├── roboto-slab-v7-regular.eot │ │ │ │ ├── roboto-slab-v7-regular.ttf │ │ │ │ ├── roboto-slab-v7-regular.woff │ │ │ │ └── roboto-slab-v7-regular.woff2 │ │ ├── documentation_options.js │ │ ├── css │ │ │ └── badge_only.css │ │ ├── js │ │ │ ├── theme.js │ │ │ └── modernizr.min.js │ │ ├── pygments.css │ │ ├── doctools.js │ │ ├── underscore.js │ │ └── basic.css │ ├── _sources │ │ ├── like.rst.txt │ │ ├── login.rst.txt │ │ ├── util.rst.txt │ │ ├── instapy.rst.txt │ │ ├── profile.rst.txt │ │ ├── unfollow.rst.txt │ │ ├── blacklist.rst.txt │ │ ├── time_util.rst.txt │ │ └── index.rst.txt │ ├── .buildinfo │ ├── search.html │ ├── profile.html │ ├── searchindex.js │ ├── index.html │ ├── py-modindex.html │ ├── time_util.html │ ├── login.html │ ├── like.html │ ├── util.html │ └── blacklist.html ├── source │ ├── .DS_Store │ ├── like.rst │ ├── util.rst │ ├── login.rst │ ├── instapy.rst │ ├── profile.rst │ ├── blacklist.rst │ ├── time_util.rst │ ├── unfollow.rst │ ├── index.rst │ └── conf.py ├── index.html ├── Makefile └── How_To_DO_Ubuntu_on_Digital_Ocean.md ├── app ├── __init__.py ├── print_log_writer.py ├── profile.py ├── time_util.py ├── login.py ├── blacklist.py └── util.py ├── db └── instapy-light.db ├── logs └── .gitignore ├── config.py └── README.md /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | from .instapy import InstaPyLight 2 | -------------------------------------------------------------------------------- /docs/erm.mwb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/erm.mwb -------------------------------------------------------------------------------- /db/instapy-light.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/db/instapy-light.db -------------------------------------------------------------------------------- /docs/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/objects.inv -------------------------------------------------------------------------------- /docs/source/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/source/.DS_Store -------------------------------------------------------------------------------- /logs/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /docs/html/_static/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/up.png -------------------------------------------------------------------------------- /docs/source/like.rst: -------------------------------------------------------------------------------- 1 | Like Features 2 | ============= 3 | 4 | .. automodule:: app.like 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/source/util.rst: -------------------------------------------------------------------------------- 1 | Util Features 2 | ============= 3 | 4 | .. automodule:: app.util 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/down.png -------------------------------------------------------------------------------- /docs/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/file.png -------------------------------------------------------------------------------- /docs/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/minus.png -------------------------------------------------------------------------------- /docs/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/plus.png -------------------------------------------------------------------------------- /docs/source/login.rst: -------------------------------------------------------------------------------- 1 | Login Features 2 | ============== 3 | 4 | .. automodule:: app.login 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/comment.png -------------------------------------------------------------------------------- /docs/source/instapy.rst: -------------------------------------------------------------------------------- 1 | Main Features 2 | ============= 3 | 4 | .. automodule:: app.instapy 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_sources/like.rst.txt: -------------------------------------------------------------------------------- 1 | Like Features 2 | ============= 3 | 4 | .. automodule:: app.like 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_sources/login.rst.txt: -------------------------------------------------------------------------------- 1 | Login Features 2 | ============== 3 | 4 | .. automodule:: app.login 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_sources/util.rst.txt: -------------------------------------------------------------------------------- 1 | Util Features 2 | ============= 3 | 4 | .. automodule:: app.util 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_static/up-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/up-pressed.png -------------------------------------------------------------------------------- /docs/source/profile.rst: -------------------------------------------------------------------------------- 1 | Profile Features 2 | ================ 3 | 4 | .. automodule:: app.profile 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_sources/instapy.rst.txt: -------------------------------------------------------------------------------- 1 | Main Features 2 | ============= 3 | 4 | .. automodule:: app.instapy 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/ajax-loader.gif -------------------------------------------------------------------------------- /docs/html/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/comment-close.png -------------------------------------------------------------------------------- /docs/html/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/down-pressed.png -------------------------------------------------------------------------------- /docs/source/blacklist.rst: -------------------------------------------------------------------------------- 1 | Blacklist Features 2 | ================== 3 | 4 | .. automodule:: app.blacklist 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/source/time_util.rst: -------------------------------------------------------------------------------- 1 | Time Util Features 2 | ================== 3 | 4 | .. automodule:: app.time_util 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/source/unfollow.rst: -------------------------------------------------------------------------------- 1 | Unfollow Features 2 | ================= 3 | 4 | .. automodule:: app.unfollow 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_sources/profile.rst.txt: -------------------------------------------------------------------------------- 1 | Profile Features 2 | ================ 3 | 4 | .. automodule:: app.profile 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/comment-bright.png -------------------------------------------------------------------------------- /docs/html/_sources/unfollow.rst.txt: -------------------------------------------------------------------------------- 1 | Unfollow Features 2 | ================= 3 | 4 | .. automodule:: app.unfollow 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_sources/blacklist.rst.txt: -------------------------------------------------------------------------------- 1 | Blacklist Features 2 | ================== 3 | 4 | .. automodule:: app.blacklist 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_sources/time_util.rst.txt: -------------------------------------------------------------------------------- 1 | Time Util Features 2 | ================== 3 | 4 | .. automodule:: app.time_util 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-bold.eot -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-bold.ttf -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-bold.woff -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-bold.woff2 -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-italic.eot -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-italic.ttf -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-italic.woff -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-regular.eot -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-regular.ttf -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-italic.woff2 -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-regular.woff -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-regular.woff2 -------------------------------------------------------------------------------- /docs/html/_static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/html/_static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-bolditalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-bolditalic.eot -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-bolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-bolditalic.ttf -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-bolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-bolditalic.woff -------------------------------------------------------------------------------- /docs/html/_static/fonts/Lato/lato-bolditalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/Lato/lato-bolditalic.woff2 -------------------------------------------------------------------------------- /docs/html/_static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/html/_static/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot -------------------------------------------------------------------------------- /docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf -------------------------------------------------------------------------------- /docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff -------------------------------------------------------------------------------- /docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 -------------------------------------------------------------------------------- /docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot -------------------------------------------------------------------------------- /docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf -------------------------------------------------------------------------------- /docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff -------------------------------------------------------------------------------- /docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/converge/InstaPy-Light/HEAD/docs/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 -------------------------------------------------------------------------------- /docs/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 24fba2c44ed63508c6b0333a04d5d32d 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: '0.1', 4 | LANGUAGE: 'None', 5 | COLLAPSE_INDEX: false, 6 | FILE_SUFFIX: '.html', 7 | HAS_SOURCE: true, 8 | SOURCELINK_SUFFIX: '.txt' 9 | }; -------------------------------------------------------------------------------- /app/print_log_writer.py: -------------------------------------------------------------------------------- 1 | """Module only used to log the number of followers to a file""" 2 | 3 | 4 | def log_followed_pool(login, followed, logger): 5 | """ 6 | Prints and logs the followed to a seperate file 7 | .. note:: 8 | Can we delete it ? 9 | """ 10 | try: 11 | with open('./logs/' + login + '_followedPool.csv', 'a+') as followPool: 12 | followPool.write(followed + ",\n") 13 | except BaseException: 14 | logger.exception('message') 15 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. InstaPy Light documentation master file, created by 2 | sphinx-quickstart on Sun Aug 26 21:10:35 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to InstaPy Light's documentation! 7 | ========================================= 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | blacklist 14 | instapy 15 | like 16 | login 17 | profile 18 | time_util 19 | unfollow 20 | util 21 | 22 | Indices and tables 23 | ================== 24 | 25 | * :ref:`genindex` 26 | * :ref:`modindex` 27 | * :ref:`search` 28 | -------------------------------------------------------------------------------- /docs/html/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | .. InstaPy Light documentation master file, created by 2 | sphinx-quickstart on Sun Aug 26 21:10:35 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to InstaPy Light's documentation! 7 | ========================================= 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | blacklist 14 | instapy 15 | like 16 | login 17 | profile 18 | time_util 19 | unfollow 20 | util 21 | 22 | Indices and tables 23 | ================== 24 | 25 | * :ref:`genindex` 26 | * :ref:`modindex` 27 | * :ref:`search` 28 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = InstaPyLight 8 | SOURCEDIR = source 9 | BUILDDIR = ../docs 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # 2 | # This is a basic configuration, all features are explained at 3 | # https://github.com/converge/InstaPy-Light 4 | # 5 | from app import InstaPyLight 6 | from random import randint, sample 7 | 8 | 9 | def get_like_n_times(): 10 | return randint(1, 3) 11 | 12 | 13 | def get_follow_n_times(): 14 | return randint(1, 3) 15 | 16 | 17 | def get_random_sleep_delay(): 18 | return randint(45, 140) 19 | 20 | 21 | def get_unfollow_n_times(): 22 | return randint(1, 3) 23 | 24 | 25 | tags = ['lawofattraction', 'datalimite', 'johnassaraf'] 26 | # from tag list, pick randomly 3 tags 27 | tags = sample(set(tags), 3) 28 | 29 | try: 30 | session = InstaPyLight(username='', 31 | password='', 32 | headless=False) 33 | session.login() 34 | finally: 35 | # it will save the last page screen before end 36 | session.save_screenshot('last_screen.png') 37 | session.end() 38 | -------------------------------------------------------------------------------- /app/profile.py: -------------------------------------------------------------------------------- 1 | """ 2 | Class to manage Profile object 3 | """ 4 | 5 | 6 | class Profile: 7 | 8 | def __init__(self): 9 | self.name = None 10 | self.blacklist_likes = None 11 | self.blacklist_follows = None 12 | self.blacklist_never_follow_again = None 13 | 14 | def set_name(self, name): 15 | self.name = name 16 | 17 | def get_name(self): 18 | return self.name 19 | 20 | def set_blacklist_likes(self, blacklist_likes): 21 | self.blacklist_like = blacklist_likes 22 | 23 | def get_blacklist_likes(self): 24 | return self.blacklist_likes 25 | 26 | def set_blacklist_follows(self, blacklist_follows): 27 | self.blacklist_follows = blacklist_follows 28 | 29 | def get_blacklist_follows(self): 30 | return self.blacklist_follows 31 | 32 | def set_blacklist_never_follow_again(self, blacklist_never_follow_again): 33 | self.blacklist_never_follow_again = blacklist_never_follow_again 34 | 35 | def get_blacklist_never_follow_again(self): 36 | return self.blacklist_never_follow_again 37 | -------------------------------------------------------------------------------- /app/time_util.py: -------------------------------------------------------------------------------- 1 | """Helper module to handle time related stuff""" 2 | from random import gauss 3 | from time import sleep as original_sleep 4 | 5 | # Amount of variance to be introduced 6 | # i.e. random time will be in the range: TIME +/- STDEV % 7 | STDEV = 0.5 8 | sleep_percentage = 1 9 | 10 | 11 | def randomize_time(mean): 12 | """ 13 | .. note:: 14 | We need to rethink it 15 | """ 16 | allowed_range = mean * STDEV 17 | stdev = allowed_range / 3 # 99.73% chance to be in the allowed range 18 | 19 | t = 0 20 | while abs(mean - t) > allowed_range: 21 | t = gauss(mean, stdev) 22 | 23 | return t 24 | 25 | 26 | def set_sleep_percentage(percentage): 27 | """ 28 | .. note:: 29 | We need to rethink it 30 | """ 31 | global sleep_percentage 32 | sleep_percentage = percentage/100 33 | 34 | 35 | def sleep(t, custom_percentage=None): 36 | """ 37 | .. note:: 38 | We need to rethink it 39 | """ 40 | if custom_percentage is None: 41 | custom_percentage = sleep_percentage 42 | time = randomize_time(t)*custom_percentage 43 | original_sleep(time) 44 | -------------------------------------------------------------------------------- /docs/How_To_DO_Ubuntu_on_Digital_Ocean.md: -------------------------------------------------------------------------------- 1 | # How to run InstaPy on a digital ocean Ubuntu droplet 2 | > Use https://m.do.co/c/be9ec19b28c1 to get 10$ free to start your InstaPy journey :wink: 3 | 4 | - #### Make sure to use the 1GB RAM version (or better) 5 | 6 | - #### Make sure to set ```nogui=True``` in your InstaPy file 7 | - #### Note that current Chrome browser and chromedriver needed for the install only support 64-bit architecture. 8 | 9 | ### General dependencies 10 | 11 | ```sh 12 | $ sudo apt-get update 13 | $ sudo apt-get -y upgrade 14 | $ sudo apt-get -y install unzip python3-pip python3-dev build-essential libssl-dev libffi-dev xvfb 15 | $ sudo pip3 install --upgrade pip 16 | $ export LANGUAGE=en_US.UTF-8 17 | $ export LANG=en_US.UTF-8 18 | $ export LC_ALL=en_US.UTF-8 19 | $ locale-gen en_US.UTF-8 20 | $ sudo dpkg-reconfigure locales 21 | $ pip3 install --upgrade pip 22 | ``` 23 | 24 | ### Chrome-stable 25 | 26 | ```sh 27 | $ cd ~ 28 | $ wget "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb" 29 | $ sudo dpkg -i google-chrome-stable_current_amd64.deb 30 | $ sudo apt-get install -y -f 31 | $ sudo rm google-chrome-stable_current_amd64.deb 32 | ``` 33 | 34 | ### InstaPy 35 | 36 | ```bash 37 | $ git clone https://github.com/timgrossmann/InstaPy.git 38 | $ wget "https://chromedriver.storage.googleapis.com/2.33/chromedriver_linux64.zip" 39 | $ unzip chromedriver_linux64 40 | $ mv chromedriver InstaPy/assets/chromedriver 41 | $ chmod +x InstaPy/assets/chromedriver 42 | $ chmod 755 InstaPy/assets/chromedriver 43 | $ cd InstaPy 44 | $ pip install . 45 | ``` 46 | -------------------------------------------------------------------------------- /docs/html/_static/css/badge_only.css: -------------------------------------------------------------------------------- 1 | .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../fonts/fontawesome-webfont.eot");src:url("../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff") format("woff"),url("../fonts/fontawesome-webfont.ttf") format("truetype"),url("../fonts/fontawesome-webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} 2 | -------------------------------------------------------------------------------- /docs/html/_static/js/theme.js: -------------------------------------------------------------------------------- 1 | /* sphinx_rtd_theme version 0.4.1 | MIT license */ 2 | /* Built 20180727 10:07 */ 3 | require=function n(e,i,t){function o(s,a){if(!i[s]){if(!e[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(r)return r(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var u=i[s]={exports:{}};e[s][0].call(u.exports,function(n){var i=e[s][1][n];return o(i||n)},u,u.exports,n,e,i,t)}return i[s].exports}for(var r="function"==typeof require&&require,s=0;s"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var i=n(this);expand=n(''),expand.on("click",function(n){return e.toggleCurrent(i),n.stopPropagation(),!1}),i.prepend(expand)})},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),i=e.find('[href="'+n+'"]');if(0===i.length){var t=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(i=e.find('[href="#'+t.attr("id")+'"]')).length&&(i=e.find('[href="#"]'))}i.length>0&&($(".wy-menu-vertical .current").removeClass("current"),i.addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l1").parent().addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l2").addClass("current"),i.closest("li.toctree-l3").addClass("current"),i.closest("li.toctree-l4").addClass("current"))}catch(o){console.log("Error expanding nav for anchor",o)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,i=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(i),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current"),e.siblings().find("li.current").removeClass("current"),e.find("> ul li.current").removeClass("current"),e.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:e.exports.ThemeNav,StickyNav:e.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],i=0;iIMAGE ALT TEXT HERE 40 | 41 | ### Setup your Instagram account 42 | 43 | 44 | 45 | ## Features 46 | 47 | ### Like By Tags 48 | 49 | - **tags** a list of tags to be used to like posts 50 | - **amount** the amount of posts you would like to like 51 | 52 | **example:** 53 | 54 | ```python 55 | tags = ['johnassaraf', 'lawofattraction'] 56 | session.like_by_tags(tags, amount=3) 57 | ``` 58 | 59 | Every tag will be liked n(amount) times. 60 | 61 | ### Follow Competitors Followers 62 | 63 | Follow your competitors followers. 64 | 65 | - **profile** list of competitors to follow their followers 66 | - **amount** the amount of profiles to be followed by competitor 67 | 68 | ```python 69 | profiles = ['instagram', 'facebook', 'spotify'] 70 | session.follow_user_followers(profiles, amount=5) 71 | ``` 72 | 73 | ### Blacklist 74 | 75 | This feature allows us to blacklist profiles **by campaign**. 76 | 77 | - **campaign** campaign name 78 | - **blacklist_likes=True** avoid liking profiles already liked 79 | - **blacklist_follows=True** avoid following already followed profiles 80 | - **never_follow_again=True** avoid unfollow and follow a profile again. After follow/unfollow process, the profile won't be followed again. 81 | 82 | **example:** 83 | 84 | ```python 85 | session.set_blacklist(campaign='blacklist_campaign', 86 | blacklist_likes=True, 87 | blacklist_follows=True, 88 | never_follow_again=True) 89 | ``` 90 | 91 | ### Unfollow by Blacklist Campaign 92 | 93 | Unfollow only profiles saved in your previous blacklist campaign 94 | 95 | - **campaign** blacklist campaign name 96 | - **amount** amount of profiles to be unfollowed 97 | 98 | ```python 99 | session.unfollow_by_blacklist_campaign(campaign='blacklist_campaign', 100 | amount=5) 101 | ``` 102 | 103 | ### Unfollow 104 | 105 | Unfollow profiles 106 | 107 | - **amount** amount of profiles to be unfollowed 108 | 109 | ```python 110 | session.unfollow_users(amount=5) 111 | ``` 112 | 113 | ### Save Screenshot 114 | 115 | This is useful when you´re running it in a server and don´t have access to the 116 | screen of the browser. If some error was raised, you can see the last screen to 117 | be able to check what could be wrong. 118 | 119 | - **filename** file name to be saved in the root folder of InstaPy-Light 120 | ```python 121 | session.save_screenshot(filename='image.png') 122 | ``` 123 | 124 | ## Developers Documentation: 125 | 126 | https://converge.github.io/InstaPy-Light 127 | 128 | ## Feedback 129 | 130 | Feel free to send me feedbacks to joaovanzuita@me.com 131 | 132 | ## Keep The Project Alive 133 | 134 | [Donate any value using Paypal](https://www.paypal.me/joaovanzuita?ppid=PPC000628&cnac=BR&rsta=en_BR%28en_AR%29&cust=Z8V4LFWNLXJ5S&unptid=9a9fa222-b75f-11e8-822d-441ea1470e54&t=&cal=62f3404cebe63&calc=62f3404cebe63&calf=62f3404cebe63&unp_tpcid=ppme-social-user-profile-created&page=main:email&pgrp=main:email&e=op&mchn=em&s=ci&mail=sys) 135 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | import os 16 | import sys 17 | sys.path.insert(0, os.path.abspath('../..')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = 'InstaPy Light' 23 | copyright = '2018, converge' 24 | author = 'converge' 25 | 26 | # The short X.Y version 27 | version = '' 28 | # The full version, including alpha/beta/rc tags 29 | release = '0.1' 30 | 31 | 32 | # -- General configuration --------------------------------------------------- 33 | 34 | # If your documentation needs a minimal Sphinx version, state it here. 35 | # 36 | # needs_sphinx = '1.0' 37 | 38 | # Add any Sphinx extension module names here, as strings. They can be 39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 40 | # ones. 41 | extensions = [ 42 | 'sphinx.ext.autodoc', 43 | 'sphinx.ext.todo' 44 | ] 45 | 46 | # Add any paths that contain templates here, relative to this directory. 47 | templates_path = ['_templates'] 48 | 49 | # The suffix(es) of source filenames. 50 | # You can specify multiple suffix as a list of string: 51 | # 52 | # source_suffix = ['.rst', '.md'] 53 | source_suffix = '.rst' 54 | 55 | # The master toctree document. 56 | master_doc = 'index' 57 | 58 | # The language for content autogenerated by Sphinx. Refer to documentation 59 | # for a list of supported languages. 60 | # 61 | # This is also used if you do content translation via gettext catalogs. 62 | # Usually you set "language" from the command line for these cases. 63 | language = None 64 | 65 | # List of patterns, relative to source directory, that match files and 66 | # directories to ignore when looking for source files. 67 | # This pattern also affects html_static_path and html_extra_path . 68 | exclude_patterns = [] 69 | 70 | # The name of the Pygments (syntax highlighting) style to use. 71 | pygments_style = 'sphinx' 72 | 73 | 74 | # -- Options for HTML output ------------------------------------------------- 75 | 76 | # The theme to use for HTML and HTML Help pages. See the documentation for 77 | # a list of builtin themes. 78 | # 79 | html_theme = 'sphinx_rtd_theme' 80 | 81 | # Theme options are theme-specific and customize the look and feel of a theme 82 | # further. For a list of options available for each theme, see the 83 | # documentation. 84 | # 85 | # html_theme_options = {} 86 | 87 | # Add any paths that contain custom static files (such as style sheets) here, 88 | # relative to this directory. They are copied after the builtin static files, 89 | # so a file named "default.css" will overwrite the builtin "default.css". 90 | html_static_path = ['_static'] 91 | 92 | # Custom sidebar templates, must be a dictionary that maps document names 93 | # to template names. 94 | # 95 | # The default sidebars (for documents that don't match any pattern) are 96 | # defined by theme itself. Builtin themes are using these templates by 97 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 98 | # 'searchbox.html']``. 99 | # 100 | # html_sidebars = {} 101 | 102 | 103 | # -- Options for HTMLHelp output --------------------------------------------- 104 | 105 | # Output file base name for HTML help builder. 106 | htmlhelp_basename = 'InstaPyLightdoc' 107 | 108 | 109 | # -- Options for LaTeX output ------------------------------------------------ 110 | 111 | latex_elements = { 112 | # The paper size ('letterpaper' or 'a4paper'). 113 | # 114 | # 'papersize': 'letterpaper', 115 | 116 | # The font size ('10pt', '11pt' or '12pt'). 117 | # 118 | # 'pointsize': '10pt', 119 | 120 | # Additional stuff for the LaTeX preamble. 121 | # 122 | # 'preamble': '', 123 | 124 | # Latex figure (float) alignment 125 | # 126 | # 'figure_align': 'htbp', 127 | } 128 | 129 | # Grouping the document tree into LaTeX files. List of tuples 130 | # (source start file, target name, title, 131 | # author, documentclass [howto, manual, or own class]). 132 | latex_documents = [ 133 | (master_doc, 'InstaPyLight.tex', 'InstaPy Light Documentation', 134 | 'converge', 'manual'), 135 | ] 136 | 137 | 138 | # -- Options for manual page output ------------------------------------------ 139 | 140 | # One entry per manual page. List of tuples 141 | # (source start file, name, description, authors, manual section). 142 | man_pages = [ 143 | (master_doc, 'instapylight', 'InstaPy Light Documentation', 144 | [author], 1) 145 | ] 146 | 147 | 148 | # -- Options for Texinfo output ---------------------------------------------- 149 | 150 | # Grouping the document tree into Texinfo files. List of tuples 151 | # (source start file, target name, title, author, 152 | # dir menu entry, description, category) 153 | texinfo_documents = [ 154 | (master_doc, 'InstaPyLight', 'InstaPy Light Documentation', 155 | author, 'InstaPyLight', 'One line description of project.', 156 | 'Miscellaneous'), 157 | ] 158 | 159 | 160 | # -- Extension configuration ------------------------------------------------- 161 | -------------------------------------------------------------------------------- /docs/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Search — InstaPy Light 0.1 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 | 42 | 43 | 96 | 97 |
98 | 99 | 100 | 106 | 107 | 108 |
109 | 110 |
111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 |
129 | 130 |
    131 | 132 |
  • Docs »
  • 133 | 134 |
  • Search
  • 135 | 136 | 137 |
  • 138 | 139 | 140 | 141 |
  • 142 | 143 |
144 | 145 | 146 |
147 |
148 |
149 |
150 | 151 | 159 | 160 | 161 |
162 | 163 |
164 | 165 |
166 | 167 |
168 |
169 | 170 | 171 |
172 | 173 |
174 |

175 | © Copyright 2018, converge. 176 | 177 |

178 |
179 | Built with Sphinx using a theme provided by Read the Docs. 180 | 181 |
182 | 183 |
184 |
185 | 186 |
187 | 188 |
189 | 190 | 191 | 192 | 193 | 194 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 219 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | -------------------------------------------------------------------------------- /docs/html/profile.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Profile Features — InstaPy Light 0.1 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 98 | 99 |
100 | 101 | 102 | 108 | 109 | 110 |
111 | 112 |
113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 |
131 | 132 |
    133 | 134 |
  • Docs »
  • 135 | 136 |
  • Profile Features
  • 137 | 138 | 139 |
  • 140 | 141 | 142 | View page source 143 | 144 | 145 |
  • 146 | 147 |
148 | 149 | 150 |
151 |
152 |
153 |
154 | 155 |
156 |

Profile Features

157 |

Class to manage Profile object

158 |
159 | 160 | 161 |
162 | 163 |
164 |
165 | 166 | 174 | 175 | 176 |
177 | 178 |
179 |

180 | © Copyright 2018, converge. 181 | 182 |

183 |
184 | Built with Sphinx using a theme provided by Read the Docs. 185 | 186 |
187 | 188 |
189 |
190 | 191 |
192 | 193 |
194 | 195 | 196 | 197 | 198 | 199 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /app/login.py: -------------------------------------------------------------------------------- 1 | """Module only used for the login part of the script""" 2 | from .time_util import sleep 3 | from selenium.webdriver.common.action_chains import ActionChains 4 | from selenium.common.exceptions import NoSuchElementException 5 | from selenium.common.exceptions import WebDriverException 6 | from .util import update_activity 7 | import pickle 8 | import sqlite3 9 | 10 | 11 | def bypass_suspicious_login(browser): 12 | """ 13 | Bypass suspicious loggin attempt verification. This should be only enabled 14 | when there isn't available cookie for the username, otherwise it will and 15 | shows "Unable to locate email or phone button" message, folollowed by 16 | CRITICAL - Wrong login data! 17 | 18 | Args: 19 | :browser: web driver 20 | """ 21 | # close sign up Instagram modal if available 22 | try: 23 | close_button = browser.find_element_by_xpath("[text()='Close']") 24 | ActionChains( 25 | browser).move_to_element(close_button).click().perform() 26 | except NoSuchElementException: 27 | pass 28 | 29 | try: 30 | # click on "This was me" button if challenge page was called 31 | this_was_me_button = browser.find_element_by_xpath( 32 | "//button[@name='choice'][text()='This Was Me']") 33 | ActionChains( 34 | browser).move_to_element(this_was_me_button).click().perform() 35 | except NoSuchElementException: 36 | # no verification needed 37 | pass 38 | 39 | try: 40 | user_email = browser.find_element_by_xpath( 41 | "//label[@for='choice_1']").text 42 | except NoSuchElementException: 43 | try: 44 | user_email = browser.find_element_by_xpath( 45 | "//label[@class='_q0nt5']").text 46 | except Exception: 47 | try: 48 | user_email = browser.find_element_by_xpath( 49 | "//label[@class='_q0nt5 _a7z3k']").text 50 | except Exception: 51 | print("Unable to locate email or phone button, maybe " 52 | "bypass_suspicious_login=True isn't needed anymore.") 53 | return False 54 | 55 | send_security_code_button = browser.find_element_by_xpath( 56 | ("//button[text()='Send Security Code']")) 57 | (ActionChains(browser) 58 | .move_to_element(send_security_code_button) 59 | .click() 60 | .perform()) 61 | 62 | print('Instagram detected an unusual login attempt') 63 | print('A security code wast sent to your {}'.format(user_email)) 64 | security_code = input('Type the security code here: ') 65 | 66 | security_code_field = browser.find_element_by_xpath(( 67 | "//input[@id='security_code']")) 68 | (ActionChains(browser) 69 | .move_to_element(security_code_field) 70 | .click().send_keys(security_code).perform()) 71 | 72 | submit_security_code_button = browser.find_element_by_xpath(( 73 | "//button[text()='Submit']")) 74 | 75 | (ActionChains(browser) 76 | .move_to_element(submit_security_code_button) 77 | .click().perform()) 78 | 79 | try: 80 | sleep(5) 81 | # locate wrong security code message 82 | wrong_login = browser.find_element_by_xpath(( 83 | "//p[text()='Please check the code we sent you and try " 84 | "again.']")) 85 | if wrong_login is not None: 86 | print(('Wrong security code! Please check the code Instagram' 87 | 'sent you and try again.')) 88 | except NoSuchElementException: 89 | # correct security code 90 | pass 91 | 92 | 93 | def login_user(browser, 94 | username, 95 | password, 96 | account_id, 97 | switch_language=True, 98 | bypass_suspicious_attempt=False): 99 | """ 100 | Logins the user with the given username and password 101 | 102 | Args: 103 | :browser: web driver 104 | :username: our username 105 | :password: password 106 | :switch_language: do we still need it ? 107 | :bypass_suspicious_login: bypass suspicious login attempt 108 | Returns: 109 | True / False 110 | """ 111 | browser.get('https://www.instagram.com') 112 | # update server calls 113 | update_activity() 114 | # try to load cookie from username 115 | try: 116 | browser.get('https://www.instagram.com') 117 | for cookie in pickle.load(open('./logs/{}_cookie.pkl' 118 | .format(username), 'rb')): 119 | browser.add_cookie(cookie) 120 | # logged in! 121 | return True 122 | except (WebDriverException, OSError, IOError): 123 | print("Cookie file not found, creating cookie...") 124 | browser.get('https://www.instagram.com') 125 | 126 | # Changes instagram language to english, to ensure no errors ensue from 127 | # having the site on a different language 128 | # Might cause problems if the OS language is english 129 | if switch_language: 130 | browser.find_element_by_xpath( 131 | "//select[@class='hztqj']/option[text()='English']").click() 132 | 133 | # Check if the first div is 'Create an Account' or 'Log In' 134 | login_elem = browser.find_element_by_xpath( 135 | "//article/div/div/p/a[text()='Log in']") 136 | if login_elem is not None: 137 | ActionChains(browser).move_to_element(login_elem).click().perform() 138 | 139 | # Enter username and password and logs the user in 140 | # Sometimes the element name isn't 'Username' and 'Password' 141 | # (valid for placeholder too) 142 | sleep(3) 143 | input_username = browser.find_elements_by_xpath( 144 | "//input[@name='username']") 145 | 146 | ActionChains(browser).move_to_element(input_username[0]). \ 147 | click().send_keys(username).perform() 148 | sleep(1) 149 | 150 | if password: 151 | input_password = browser.find_elements_by_xpath( 152 | "//input[@name='password']") 153 | else: 154 | input_password = browser.find_elements_by_xpath( 155 | "//input[@name='password']") 156 | 157 | # input password 158 | ActionChains(browser).move_to_element(input_password[0]). \ 159 | click().send_keys(password).perform() 160 | 161 | login_button = browser.find_element_by_xpath( 162 | "//form/span/button[text()='Log in']") 163 | ActionChains(browser).move_to_element(login_button).click().perform() 164 | # update server calls 165 | update_activity() 166 | 167 | if bypass_suspicious_attempt is True: 168 | bypass_suspicious_login(browser) 169 | 170 | sleep(5) 171 | 172 | # Check if user is logged-in (If there's two 'nav' elements) 173 | nav = browser.find_elements_by_xpath('//nav') 174 | if len(nav) == 2: 175 | # create cookie for username 176 | pickle.dump(browser.get_cookies(), 177 | open('./logs/{}_cookie.pkl'.format(username), 'wb')) 178 | return True 179 | else: 180 | return False 181 | -------------------------------------------------------------------------------- /docs/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({docnames:["blacklist","index","instapy","like","login","profile","time_util","unfollow","util"],envversion:53,filenames:["blacklist.rst","index.rst","instapy.rst","like.rst","login.rst","profile.rst","time_util.rst","unfollow.rst","util.rst"],objects:{"app.blacklist":{add_user_to_blacklist:[0,1,1,""],get_followed_by_campaign:[0,1,1,""],get_profiles_from_blacklist_campaign:[0,1,1,""],is_user_in_followed_blacklist:[0,1,1,""],is_user_in_liked_blacklist:[0,1,1,""],mark_as_unfollowed_by_blacklist_campaign:[0,1,1,""]},"app.instapy":{InstaPyLight:[2,2,1,""]},"app.instapy.InstaPyLight":{cancel_pending_follow_requests:[2,3,1,""],end:[2,3,1,""],follow_by_list:[2,3,1,""],follow_user_followers:[2,3,1,""],follow_user_following:[2,3,1,""],interact_by_users:[2,3,1,""],interact_user_followers:[2,3,1,""],interact_user_following:[2,3,1,""],like_by_feed:[2,3,1,""],like_by_locations:[2,3,1,""],like_by_tags:[2,3,1,""],like_by_users:[2,3,1,""],like_from_image:[2,3,1,""],login:[2,3,1,""],save_screenshot:[2,3,1,""],set_blacklist:[2,3,1,""],set_do_follow:[2,3,1,""],set_dont_like:[2,3,1,""],set_dont_touch:[2,3,1,""],set_dont_unfollow_active_users:[2,3,1,""],set_ignore_if_contains:[2,3,1,""],set_lower_follower_count:[2,3,1,""],set_selenium_local_session:[2,3,1,""],set_selenium_remote_session:[2,3,1,""],set_sleep_reduce:[2,3,1,""],set_smart_hashtags:[2,3,1,""],set_upper_follower_count:[2,3,1,""],set_use_clarifai:[2,3,1,""],set_user_interact:[2,3,1,""],unfollow_by_blacklist_campaign:[2,3,1,""],unfollow_users:[2,3,1,""],whats_my_ip:[2,3,1,""]},"app.like":{check_link:[3,1,1,""],get_links_for_location:[3,1,1,""],get_links_for_tag:[3,1,1,""],get_links_for_username:[3,1,1,""],get_links_from_feed:[3,1,1,""],get_tags:[3,1,1,""],like_image:[3,1,1,""]},"app.login":{bypass_suspicious_login:[4,1,1,""],login_user:[4,1,1,""]},"app.time_util":{randomize_time:[6,1,1,""],set_sleep_percentage:[6,1,1,""],sleep:[6,1,1,""]},"app.unfollow":{cancel_pending_requests:[7,1,1,""],follow_given_user:[7,1,1,""],follow_given_user_followers:[7,1,1,""],follow_given_user_following:[7,1,1,""],follow_through_dialog:[7,1,1,""],follow_user:[7,1,1,""],get_given_user_followers:[7,1,1,""],get_given_user_following:[7,1,1,""],unfollow:[7,1,1,""],unfollow_profile_from_campaign:[7,1,1,""],unfollow_user:[7,1,1,""]},"app.util":{formatNumber:[8,1,1,""],get_account_id:[8,1,1,""],get_active_users:[8,1,1,""],is_account_active:[8,1,1,""],scroll_bottom:[8,1,1,""],update_activity:[8,1,1,""],validate_username:[8,1,1,""]},app:{blacklist:[0,0,0,"-"],instapy:[2,0,0,"-"],like:[3,0,0,"-"],login:[4,0,0,"-"],profile:[5,0,0,"-"],time_util:[6,0,0,"-"],unfollow:[7,0,0,"-"],util:[8,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"],"2":["py","class","Python class"],"3":["py","method","Python method"]},objtypes:{"0":"py:module","1":"py:function","2":"py:class","3":"py:method"},terms:{"class":[2,5],"default":2,"return":[0,3,4,7,8],"true":[0,2,3,4,7,8],Used:2,Useful:2,abov:8,acc_to_follow:7,account:[0,2,3,7,8],account_id:[0,3,4,7],action:[0,3,7,8],activ:8,actual:2,add:0,add_user_to_blacklist:0,added:0,address:2,after:2,again:2,all:[0,3,7,8],all_follow:7,allfollow:7,allow:2,amount:[2,3,7,8],ani:2,api:2,api_kei:2,app:[0,2,3,4,6,7,8],arg:[0,2,3,4,7,8],attempt:4,auto:2,autom:2,avail:[2,4],back:[],ban:2,base:[2,8],black:0,blacklist:[1,2,3,7,8],blacklist_follow:2,blacklist_lik:2,browser:[0,3,4,7,8],button:4,bypass:4,bypass_suspicious_attempt:[2,4],bypass_suspicious_login:4,calcul:8,call:[2,8],callback:7,campaign:[0,2,7],campaign_nam:2,can:[2,7,8],cancel:7,cancel_pending_follow_request:2,cancel_pending_request:7,certain:2,chang:2,check:[0,2,3,8],check_link:3,chose:2,clarifai:2,close:2,collect:2,com:2,comment:8,competitor:[2,7],consult:8,contain:2,content:[1,8],cooki:4,correct:7,count:7,critic:4,current:[2,7],custom_percentag:6,data:4,databas:0,defin:2,delai:7,delet:2,deprec:7,descript:[2,3],develop:2,dialog:7,displaypurpos:2,doc:7,docker:2,doesn:8,doesnt:[],don:[2,8],done:0,dont:7,dont_includ:7,dont_lik:3,dont_touch:7,down:8,driver:[0,3,4,7,8],each:2,either:2,element:8,email:4,enabl:[2,4],end:2,everi:[2,7,8],exampl:2,exist:3,fals:[0,2,3,4,7,8],featur:1,feed:[2,3],fetch:3,filenam:2,filter:[2,8],follow:[0,2,7,8],follow_by_list:2,follow_given_us:7,follow_given_user_follow:7,follow_restrict:7,follow_through_dialog:7,follow_us:7,follow_user_follow:2,followlist:2,folollow:4,format:8,formatnumb:8,from:[0,2,3,7],full_match:2,gener:2,get:[0,2,3],get_account_id:8,get_active_us:8,get_followed_by_campaign:0,get_given_user_follow:7,get_links_for_loc:3,get_links_for_tag:3,get_links_for_usernam:3,get_links_from_fe:3,get_profiles_from_blacklist_campaign:0,get_tag:3,given:[2,3,4,7],goe:7,handl:[3,6,7],has:2,hashtag:2,have:2,headless:2,helper:6,hous:8,http:2,idea:8,ignor:2,ignore_if_contain:3,imag:[2,3,7],img:2,index:[1,7],initi:2,insid:2,instagram:[3,7,8],instapi:2,instapylight:2,interact:[2,8],interact_by_us:2,interact_user_follow:2,invalid:8,is_account_act:8,is_user_in_followed_blacklist:0,is_user_in_liked_blacklist:0,isn:4,know:8,latest:[2,8],librari:[0,3,7,8],like:[0,1,2,7,8],like_by_fe:2,like_by_followers_lower_limit:[3,8],like_by_followers_upper_limit:[3,8],like_by_loc:2,like_by_tag:2,like_by_us:2,like_from_imag:2,like_imag:3,limit:[2,8],link:3,list:[0,2,3,7,8],load:[7,8],local:2,locat:[2,3,4],log:[0,3,7,8],log_tag:2,logger:[0,3,7,8],loggin:4,login:[1,2,7],login_us:4,main:1,mama:8,manag:5,mark:[0,2,7],mark_as_unfollowed_by_blacklist_campaign:0,mean:6,media:[2,3],messag:4,modul:[1,3,4,6,7],month:2,more:8,name:[0,2,7,8],need:[2,4,6,8],never:2,never_follow_again:2,nogui:2,none:[2,3,6,8],num_of_search:3,number:[2,3,8],object:5,onc:8,one:2,onli:[2,4],onlynotfollowm:2,open:[3,7],otherwis:4,our:[3,4,7,8],out:2,page:[1,8],page_delai:2,part:4,password:[2,4],pend:7,per:2,percentag:[2,6],phone:4,photo:2,place:8,possibl:2,post:[2,3,8],prevent:2,process:7,profil:[0,1,2,3,7,8],profile1:2,profile2:2,profile3:2,project:2,proxy_address:2,proxy_port:2,rand_int:8,random:[2,3,7],randomize_tim:6,randomli:[2,7],range_int:8,rank:2,receiv:8,record:8,refus:7,relat:[6,8],remot:2,renam:7,reorgan:8,request:7,respect:2,restrict:2,rethink:6,retriev:[2,7],rule:2,same:7,save:2,save_screenshot:2,scrap:2,screen:2,script:4,scroll:8,scroll_bottom:8,search:1,selenium:2,selenium_local_sess:2,selenium_url:2,server:[2,8],session:2,set_blacklist:2,set_do_follow:2,set_dont_lik:2,set_dont_touch:2,set_dont_unfollow_active_us:2,set_ignore_if_contain:2,set_lower_follower_count:2,set_selenium_local_sess:2,set_selenium_remote_sess:2,set_sleep_percentag:6,set_sleep_reduc:2,set_smart_hashtag:2,set_upper_follower_count:2,set_use_clarifai:2,set_user_interact:2,setup:[0,2,3,7,8],shot:2,should:[2,4,7],show:4,show_log:2,sinc:7,skip:2,skip_top_post:[2,3],sleep:6,sleep_delai:2,smart:2,some:2,sort:2,spammi:2,specifi:3,start:2,still:4,stuff:6,suspici:4,switch_languag:4,tag:[2,3],thi:[2,4,7,8],time:[1,2],time_util:6,top:2,unabl:4,under:2,unfollow:[0,1,2,8],unfollow_by_blacklist_campaign:2,unfollow_profile_from_campaign:7,unfollow_us:[2,7],unform:8,updat:0,update_act:8,url:[2,3],use_firefox:[],use_smart_hashtag:2,used:[2,4],user:[0,2,4,7,8],user_nam:7,usernam:[0,2,3,4,7,8],using:[7,8],util:1,valid:3,validate_usernam:8,verif:4,verifi:8,version:7,video:2,web:[0,3,4,7,8],whats_my_ip:2,when:[4,8],where:8,which:[2,7],who:[2,8],window:7,won:2,word:2,work:2,wrong:4,wtf:8,your:2},titles:["Blacklist Features","Welcome to InstaPy Light\u2019s documentation!","Main Features","Like Features","Login Features","Profile Features","Time Util Features","Unfollow Features","Util Features"],titleterms:{blacklist:0,document:1,featur:[0,2,3,4,5,6,7,8],indic:1,instapi:1,light:1,like:3,login:4,main:2,profil:5,tabl:1,time:6,unfollow:7,util:[6,8],welcom:1}}) -------------------------------------------------------------------------------- /app/blacklist.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | from .profile import Profile 3 | from .util import DATABASE_LOCATION 4 | 5 | 6 | def get_profiles_from_blacklist_campaign(blacklist, username, logger): 7 | """ 8 | Returns all users from a blacklist campaign 9 | 10 | Args: 11 | :blacklist: blacklist setup 12 | :account_id: username account id 13 | :logger: library to log actions 14 | Returns: 15 | list of profile names from the campaign 16 | """ 17 | profiles = [] 18 | try: 19 | conn = sqlite3.connect(DATABASE_LOCATION) 20 | with conn: 21 | conn.row_factory = sqlite3.Row 22 | cur = conn.cursor() 23 | sql = ( 24 | "SELECT profile, campaign, liked, followed, " 25 | "never_follow_again FROM blacklist " 26 | "WHERE campaign = ? " 27 | " AND profile = ?" 28 | " AND liked = ?" 29 | " AND never_follow_again = ?" 30 | "GROUP BY profile") 31 | cur.execute(sql, (blacklist['campaign'], 32 | username, 33 | blacklist['blacklist_likes'], 34 | blacklist['never_follow_again'])) 35 | data = cur.fetchall() 36 | if data is not None: 37 | for p in data: 38 | profile = Profile() 39 | profile.set_name(p['profile']) 40 | profile.set_blacklist_likes(p['liked']) 41 | profile.set_blacklist_follows(p['following']) 42 | profile.set_blacklist_never_follow_again( 43 | p['never_follow_again']) 44 | profiles.append(profile) 45 | logger.info( 46 | 'There are {} profiles in "{}" blacklist campaign' 47 | .format(len(data), blacklist['campaign'])) 48 | else: 49 | logger.info( 50 | "First time campaign '{}' is running" 51 | .format(blacklist['campaign'])) 52 | return profiles 53 | except Exception: 54 | logger.exception('message') 55 | 56 | 57 | def get_followed_by_campaign(campaign): 58 | """ 59 | Get all followed users from a blacklist campaign 60 | 61 | Args: 62 | :campaign: blacklist campaign name 63 | Returns: 64 | List of profiles followed by the campaign 65 | """ 66 | conn = sqlite3.connect(DATABASE_LOCATION) 67 | followed = [] 68 | with conn: 69 | conn.row_factory = sqlite3.Row 70 | cur = conn.cursor() 71 | sql = ( 72 | "SELECT profile FROM blacklist WHERE campaign = ? AND " 73 | "followed = 1") 74 | cur.execute(sql, (campaign,)) 75 | data = cur.fetchall() 76 | if data is not None: 77 | for profile in data: 78 | followed.append(profile['profile']) 79 | return followed 80 | 81 | 82 | def add_user_to_blacklist(account_id, 83 | browser, 84 | profile, 85 | blacklist, 86 | action, 87 | logger): 88 | """ 89 | Adds a profile to user blacklist campaign 90 | 91 | Args: 92 | :account_id: account_id of the logged in username 93 | :browser: web driver 94 | :profile: profile to be added to blacklist campaign 95 | :blacklist: blacklist setup 96 | :action: action done by the user (like or follow) 97 | :logger: library to log actions. 98 | """ 99 | if action == 'like': 100 | try: 101 | conn = sqlite3.connect(DATABASE_LOCATION) 102 | with conn: 103 | conn.row_factory = sqlite3.Row 104 | cur = conn.cursor() 105 | sql = ("INSERT OR REPLACE INTO blacklist " 106 | "(account_id, profile, campaign, liked, created) " 107 | "VALUES (?, ?, ?, ?, date('now'))") 108 | cur.execute(sql, (account_id, 109 | profile, 110 | blacklist['campaign'], 111 | blacklist['blacklist_likes'],)) 112 | conn.commit() 113 | 114 | logger.info('--> {} added to blacklist for "{}" campaign' 115 | '(action: {})' 116 | .format(profile, blacklist['campaign'], action)) 117 | except Exception: 118 | logger.exception('message') 119 | 120 | elif action == 'follow': 121 | try: 122 | conn = sqlite3.connect(DATABASE_LOCATION) 123 | with conn: 124 | conn.row_factory = sqlite3.Row 125 | cur = conn.cursor() 126 | sql = ("INSERT OR REPLACE INTO blacklist " 127 | "(account_id, profile, campaign, followed, " 128 | "never_follow_again, created) " 129 | "VALUES (?, ?, ?, ?, ?, date('now'))") 130 | cur.execute(sql, (account_id, 131 | profile, 132 | blacklist['campaign'], 133 | blacklist['blacklist_follows'], 134 | blacklist['never_follow_again'],)) 135 | conn.commit() 136 | 137 | logger.info('--> {} added to blacklist for "{}" campaign ' 138 | '(action: {})' 139 | .format(profile, blacklist['campaign'], action)) 140 | except Exception: 141 | logger.exception('message') 142 | 143 | 144 | def mark_as_unfollowed_by_blacklist_campaign(profile, campaign, logger): 145 | """ 146 | Update database marking the profile as unfollowed by the blacklist campaign 147 | 148 | Args: 149 | :profile: profile to by marked as unfollowed by blacklist campaign 150 | :campaign: black campaign name 151 | :logger: library to log actions 152 | """ 153 | try: 154 | conn = sqlite3.connect(DATABASE_LOCATION) 155 | with conn: 156 | conn.row_factory = sqlite3.Row 157 | cur = conn.cursor() 158 | sql = ("UPDATE blacklist " 159 | "SET followed = 0 " 160 | "WHERE profile = ? " 161 | "AND campaign = ?") 162 | cur.execute(sql, (profile, campaign,)) 163 | conn.commit() 164 | except Exception: 165 | logger.exception('message') 166 | 167 | 168 | def is_user_in_followed_blacklist(profile, blacklist): 169 | """ 170 | Check if profile is in blacklist (followed by the blacklist campaign) 171 | 172 | Args: 173 | :profile: profile to be checked 174 | :blacklist: blacklist setup 175 | Returns: 176 | True or False 177 | """ 178 | if blacklist['enabled'] is True: 179 | if profile in blacklist['followed_profiles']: 180 | return True 181 | return False 182 | 183 | 184 | def is_user_in_liked_blacklist(profile, blacklist): 185 | """ 186 | Check if profile is in blacklist (liked by the blacklist campaign) 187 | 188 | Args: 189 | :profile: profile to be checked 190 | :blacklist: blacklist setup 191 | Returns: 192 | True or False 193 | """ 194 | if blacklist['campaign']: 195 | if profile in blacklist['liked_profiles']: 196 | return True 197 | return False 198 | -------------------------------------------------------------------------------- /docs/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Welcome to InstaPy Light’s documentation! — InstaPy Light 0.1 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 | 43 | 44 | 97 | 98 |
99 | 100 | 101 | 107 | 108 | 109 |
110 | 111 |
112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 |
130 | 131 |
    132 | 133 |
  • Docs »
  • 134 | 135 |
  • Welcome to InstaPy Light’s documentation!
  • 136 | 137 | 138 |
  • 139 | 140 | 141 | View page source 142 | 143 | 144 |
  • 145 | 146 |
147 | 148 | 149 |
150 |
151 |
152 |
153 | 154 |
155 |

Welcome to InstaPy Light’s documentation!

156 |
157 |

Contents:

158 | 168 |
169 |
170 |
171 |

Indices and tables

172 | 177 |
178 | 179 | 180 |
181 | 182 |
183 |
184 | 185 | 191 | 192 | 193 |
194 | 195 |
196 |

197 | © Copyright 2018, converge. 198 | 199 |

200 |
201 | Built with Sphinx using a theme provided by Read the Docs. 202 | 203 |
204 | 205 |
206 |
207 | 208 |
209 | 210 |
211 | 212 | 213 | 214 | 215 | 216 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 240 | 241 | 242 | -------------------------------------------------------------------------------- /docs/html/py-modindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Python Module Index — InstaPy Light 0.1 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 | 45 | 46 | 99 | 100 |
101 | 102 | 103 | 109 | 110 | 111 |
112 | 113 |
114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 |
132 | 133 |
    134 | 135 |
  • Docs »
  • 136 | 137 |
  • Python Module Index
  • 138 | 139 | 140 |
  • 141 | 142 |
  • 143 | 144 |
145 | 146 | 147 |
148 |
149 |
150 |
151 | 152 | 153 |

Python Module Index

154 | 155 |
156 | a 157 |
158 | 159 | 160 | 161 | 163 | 164 | 166 | 169 | 170 | 171 | 174 | 175 | 176 | 179 | 180 | 181 | 184 | 185 | 186 | 189 | 190 | 191 | 194 | 195 | 196 | 199 | 200 | 201 | 204 | 205 | 206 | 209 |
 
162 | a
167 | app 168 |
    172 | app.blacklist 173 |
    177 | app.instapy 178 |
    182 | app.like 183 |
    187 | app.login 188 |
    192 | app.profile 193 |
    197 | app.time_util 198 |
    202 | app.unfollow 203 |
    207 | app.util 208 |
210 | 211 | 212 |
213 | 214 |
215 |
216 | 217 | 218 |
219 | 220 |
221 |

222 | © Copyright 2018, converge. 223 | 224 |

225 |
226 | Built with Sphinx using a theme provided by Read the Docs. 227 | 228 |
229 | 230 |
231 |
232 | 233 |
234 | 235 |
236 | 237 | 238 | 239 | 240 | 241 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 265 | 266 | 267 | -------------------------------------------------------------------------------- /docs/html/time_util.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Time Util Features — InstaPy Light 0.1 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 98 | 99 |
100 | 101 | 102 | 108 | 109 | 110 |
111 | 112 |
113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 |
131 | 132 |
    133 | 134 |
  • Docs »
  • 135 | 136 |
  • Time Util Features
  • 137 | 138 | 139 |
  • 140 | 141 | 142 | View page source 143 | 144 | 145 |
  • 146 | 147 |
148 | 149 | 150 |
151 |
152 |
153 |
154 | 155 |
156 |

Time Util Features

157 |

Helper module to handle time related stuff

158 |
159 |
160 | app.time_util.randomize_time(mean)
161 |
162 |

Note

163 |

We need to rethink it

164 |
165 |
166 | 167 |
168 |
169 | app.time_util.set_sleep_percentage(percentage)
170 |
171 |

Note

172 |

We need to rethink it

173 |
174 |
175 | 176 |
177 |
178 | app.time_util.sleep(t, custom_percentage=None)
179 |
180 |

Note

181 |

We need to rethink it

182 |
183 |
184 | 185 |
186 | 187 | 188 |
189 | 190 |
191 |
192 | 193 | 201 | 202 | 203 |
204 | 205 |
206 |

207 | © Copyright 2018, converge. 208 | 209 |

210 |
211 | Built with Sphinx using a theme provided by Read the Docs. 212 | 213 |
214 | 215 |
216 |
217 | 218 |
219 | 220 |
221 | 222 | 223 | 224 | 225 | 226 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /app/util.py: -------------------------------------------------------------------------------- 1 | """ 2 | When we don`t know where to place a feature, this is mamas house 3 | """ 4 | from .time_util import sleep 5 | from selenium.common.exceptions import NoSuchElementException 6 | import sqlite3 7 | 8 | 9 | DATABASE_LOCATION = './db/instapy-light.db' 10 | 11 | 12 | def validate_username(browser, 13 | username, 14 | blacklist, 15 | like_by_followers_upper_limit, 16 | like_by_followers_lower_limit): 17 | """ 18 | Check if we can interact with the user 19 | 20 | Args: 21 | :browser: web driver 22 | :username: our username 23 | :blacklist: blacklist setup 24 | :like_by_followers_upper_limit: <- 25 | :like_by_followers_lower_limit: <- 26 | 27 | .. note:: are we using it ? 28 | """ 29 | 30 | if username in blacklist: 31 | return '---> {} is in blacklist, skipping user...' 32 | 33 | browser.get('https://www.instagram.com/{}'.format(username)) 34 | sleep(1) 35 | try: 36 | followers = (formatNumber(browser.find_element_by_xpath("//a[contains" 37 | "(@href,'followers')]/span").text)) 38 | except NoSuchElementException: 39 | return '---> {} account is private, skipping user...'.format(username) 40 | 41 | if like_by_followers_upper_limit != 0 or like_by_followers_lower_limit != 0: 42 | if followers > like_by_followers_upper_limit: 43 | return '---> User {} exceeds followers limit'.format(username) 44 | elif followers < like_by_followers_lower_limit: 45 | return ('---> {}, number of followers does not reach ' 46 | 'minimum'.format(username)) 47 | 48 | # if everything ok 49 | return True 50 | 51 | 52 | def update_activity(action=None): 53 | """ 54 | Record every Instagram server call (page load, content load, likes, 55 | comments, follows, unfollow). 56 | 57 | .. note:: we need to reorganize this idea 58 | """ 59 | conn = sqlite3.connect(DATABASE_LOCATION) 60 | with conn: 61 | conn.row_factory = sqlite3.Row 62 | cur = conn.cursor() 63 | # collect today data 64 | cur.execute("SELECT * FROM statistics WHERE created == date('now')") 65 | data = cur.fetchone() 66 | 67 | if data is None: 68 | # create a new record for the new day 69 | cur.execute("INSERT INTO statistics VALUES " 70 | "(0, 0, 0, 0, 1, date('now'))") 71 | else: 72 | # sqlite3.Row' object does not support item assignment -> so, 73 | # convert it into a new dict 74 | data = dict(data) 75 | # update 76 | data['server_calls'] += 1 77 | 78 | if action == 'likes': 79 | data['likes'] += 1 80 | elif action == 'comments': 81 | data['comments'] += 1 82 | elif action == 'follows': 83 | data['follows'] += 1 84 | elif action == 'unfollows': 85 | data['unfollows'] += 1 86 | 87 | sql = ("UPDATE statistics set likes = ?, comments = ?, " 88 | "follows = ?, unfollows = ?, server_calls = ? " 89 | "WHERE created = date('now')") 90 | cur.execute(sql, (data['likes'], data['comments'], data['follows'], 91 | data['unfollows'], data['server_calls'])) 92 | # commit 93 | conn.commit() 94 | 95 | 96 | def get_active_users(browser, username, posts, logger): 97 | """ 98 | Returns a list with users who liked the latest posts 99 | 100 | Args: 101 | :browser: web driver 102 | :username: our username 103 | :posts: amount of posts to be verified 104 | :logger: library to log actions 105 | Returns: 106 | Active Users based on filter above 107 | """ 108 | 109 | browser.get('https://www.instagram.com/' + username) 110 | sleep(2) 111 | 112 | total_posts = formatNumber(browser.find_element_by_xpath( 113 | "//span[contains(@class,'_t98z6')]//span").text) 114 | 115 | # if posts > total user posts, assume total posts 116 | if posts >= total_posts: 117 | # reaches all user posts 118 | posts = total_posts 119 | 120 | # click latest post 121 | browser.find_element_by_xpath( 122 | "(//div[contains(@class, '_si7dy')])[1]").click() 123 | 124 | active_users = [] 125 | 126 | # posts argument is the number of posts to collect usernames 127 | for count in range(1, posts): 128 | try: 129 | browser.find_element_by_xpath( 130 | "//a[contains(@class, '_nzn1h')]").click() 131 | sleep(1) 132 | tmp_list = browser.find_elements_by_xpath( 133 | "//a[contains(@class, '_2g7d5')]") 134 | except NoSuchElementException: 135 | try: 136 | tmp_list = browser.find_elements_by_xpath( 137 | "//div[contains(@class, '_3gwk6')]/a") 138 | except NoSuchElementException: 139 | logger.exception('message') 140 | 141 | if len(tmp_list) is not 0: 142 | for user in tmp_list: 143 | active_users.append(user.text) 144 | 145 | sleep(1) 146 | # if not reached posts(parameter) value, continue 147 | if count+1 != posts: 148 | try: 149 | # click next button 150 | browser.find_element_by_xpath( 151 | "//a[@class='_3a693 coreSpriteRightPaginationArrow']" 152 | "[text()='Next']").click() 153 | except Exception: 154 | logger.exception('message') 155 | 156 | # delete duplicated users 157 | active_users = list(set(active_users)) 158 | 159 | return active_users 160 | 161 | 162 | def scroll_bottom(browser, element, range_int): 163 | """ 164 | Instagram doesn`t load all content once, and we need to scroll the pages 165 | down to load more content 166 | 167 | Args: 168 | :browser: web driver 169 | :element: web page element to be scrolled 170 | :rand_int: calculates the scrolling limit 171 | Returns: 172 | wtf? 173 | 174 | .. todo:: why are we returning nothing here ? 175 | """ 176 | # put a limit to the scrolling 177 | if range_int > 50: 178 | range_int = 50 179 | 180 | for i in range(int(range_int / 2)): 181 | browser.execute_script( 182 | "arguments[0].scrollTop = arguments[0].scrollHeight", element) 183 | # update server calls 184 | update_activity() 185 | sleep(1) 186 | 187 | return 188 | 189 | 190 | def formatNumber(number): 191 | """ 192 | Receive an unformated number an return a formated number 193 | """ 194 | formattedNum = number.replace(',', '').replace('.', '') 195 | formattedNum = int(formattedNum.replace('k', '00').replace('m', '00000')) 196 | return formattedNum 197 | 198 | 199 | def is_account_active(browser, profile): 200 | """ 201 | Check if it`s an active Instagram Account 202 | 203 | Args: 204 | :browser: web driver 205 | :profile: profile name to be checked 206 | Returns: 207 | True for active profiles / False for invalid profiles 208 | """ 209 | browser.get('https://www.instagram.com/{}'.format(profile)) 210 | browser.implicitly_wait(3) 211 | try: 212 | browser.find_element_by_xpath('//h2/self::h2') 213 | except Exception: 214 | browser.implicitly_wait(0) 215 | # is active 216 | return True 217 | # is desactive 218 | browser.implicitly_wait(0) 219 | return False 220 | 221 | 222 | def register_account(username): 223 | conn = sqlite3.connect(DATABASE_LOCATION) 224 | with conn: 225 | cur = conn.cursor() 226 | # INSERT OR REPLACE 227 | sql = ( 228 | "INSERT OR IGNORE INTO accounts (username, modified, created) " 229 | "VALUES (?, date('now'), date('now'))") 230 | cur.execute(sql, (username, )) 231 | conn.commit() 232 | 233 | 234 | def get_account_id(username): 235 | """ 236 | Return the related account id 237 | 238 | Args: 239 | :username: username to be consulted 240 | """ 241 | conn = sqlite3.connect(DATABASE_LOCATION) 242 | with conn: 243 | conn.row_factory = sqlite3.Row 244 | cur = conn.cursor() 245 | sql = "SELECT id FROM accounts WHERE username = ?" 246 | cur.execute(sql, (username,)) 247 | data = cur.fetchone() 248 | if data is not None: 249 | return data['id'] 250 | -------------------------------------------------------------------------------- /docs/html/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Login Features — InstaPy Light 0.1 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 98 | 99 |
100 | 101 | 102 | 108 | 109 | 110 |
111 | 112 |
113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 |
131 | 132 |
    133 | 134 |
  • Docs »
  • 135 | 136 |
  • Login Features
  • 137 | 138 | 139 |
  • 140 | 141 | 142 | View page source 143 | 144 | 145 |
  • 146 | 147 |
148 | 149 | 150 |
151 |
152 |
153 |
154 | 155 |
156 |

Login Features

157 |

Module only used for the login part of the script

158 |
159 |
160 | app.login.bypass_suspicious_login(browser)
161 |

Bypass suspicious loggin attempt verification. This should be only enabled 162 | when there isn’t available cookie for the username, otherwise it will and 163 | shows “Unable to locate email or phone button” message, folollowed by 164 | CRITICAL - Wrong login data!

165 |
166 |
Args:
167 |
168 | 169 | 170 | 171 | 172 | 173 | 174 |
browser:web driver
175 |
176 |
177 |
178 | 179 |
180 |
181 | app.login.login_user(browser, username, password, account_id, switch_language=True, bypass_suspicious_attempt=False)
182 |

Logins the user with the given username and password

183 |
184 |
Args:
185 |
186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 |
browser:web driver
username:our username
password:password
switch_language:
 do we still need it ?
bypass_suspicious_login:
 bypass suspicious login attempt
203 |
204 |
Returns:
205 |
True / False
206 |
207 |
208 | 209 |
210 | 211 | 212 |
213 | 214 |
215 |
216 | 217 | 225 | 226 | 227 |
228 | 229 |
230 |

231 | © Copyright 2018, converge. 232 | 233 |

234 |
235 | Built with Sphinx using a theme provided by Read the Docs. 236 | 237 |
238 | 239 |
240 |
241 | 242 |
243 | 244 |
245 | 246 | 247 | 248 | 249 | 250 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 274 | 275 | 276 | -------------------------------------------------------------------------------- /docs/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Sphinx JavaScript utilities for all documentation. 6 | * 7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /** 13 | * select a different prefix for underscore 14 | */ 15 | $u = _.noConflict(); 16 | 17 | /** 18 | * make the code below compatible with browsers without 19 | * an installed firebug like debugger 20 | if (!window.console || !console.firebug) { 21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir", 22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", 23 | "profile", "profileEnd"]; 24 | window.console = {}; 25 | for (var i = 0; i < names.length; ++i) 26 | window.console[names[i]] = function() {}; 27 | } 28 | */ 29 | 30 | /** 31 | * small helper function to urldecode strings 32 | */ 33 | jQuery.urldecode = function(x) { 34 | return decodeURIComponent(x).replace(/\+/g, ' '); 35 | }; 36 | 37 | /** 38 | * small helper function to urlencode strings 39 | */ 40 | jQuery.urlencode = encodeURIComponent; 41 | 42 | /** 43 | * This function returns the parsed url parameters of the 44 | * current request. Multiple values per key are supported, 45 | * it will always return arrays of strings for the value parts. 46 | */ 47 | jQuery.getQueryParameters = function(s) { 48 | if (typeof s === 'undefined') 49 | s = document.location.search; 50 | var parts = s.substr(s.indexOf('?') + 1).split('&'); 51 | var result = {}; 52 | for (var i = 0; i < parts.length; i++) { 53 | var tmp = parts[i].split('=', 2); 54 | var key = jQuery.urldecode(tmp[0]); 55 | var value = jQuery.urldecode(tmp[1]); 56 | if (key in result) 57 | result[key].push(value); 58 | else 59 | result[key] = [value]; 60 | } 61 | return result; 62 | }; 63 | 64 | /** 65 | * highlight a given string on a jquery object by wrapping it in 66 | * span elements with the given class name. 67 | */ 68 | jQuery.fn.highlightText = function(text, className) { 69 | function highlight(node, addItems) { 70 | if (node.nodeType === 3) { 71 | var val = node.nodeValue; 72 | var pos = val.toLowerCase().indexOf(text); 73 | if (pos >= 0 && 74 | !jQuery(node.parentNode).hasClass(className) && 75 | !jQuery(node.parentNode).hasClass("nohighlight")) { 76 | var span; 77 | var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); 78 | if (isInSVG) { 79 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 80 | } else { 81 | span = document.createElement("span"); 82 | span.className = className; 83 | } 84 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 85 | node.parentNode.insertBefore(span, node.parentNode.insertBefore( 86 | document.createTextNode(val.substr(pos + text.length)), 87 | node.nextSibling)); 88 | node.nodeValue = val.substr(0, pos); 89 | if (isInSVG) { 90 | var bbox = span.getBBox(); 91 | var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); 92 | rect.x.baseVal.value = bbox.x; 93 | rect.y.baseVal.value = bbox.y; 94 | rect.width.baseVal.value = bbox.width; 95 | rect.height.baseVal.value = bbox.height; 96 | rect.setAttribute('class', className); 97 | var parentOfText = node.parentNode.parentNode; 98 | addItems.push({ 99 | "parent": node.parentNode, 100 | "target": rect}); 101 | } 102 | } 103 | } 104 | else if (!jQuery(node).is("button, select, textarea")) { 105 | jQuery.each(node.childNodes, function() { 106 | highlight(this, addItems); 107 | }); 108 | } 109 | } 110 | var addItems = []; 111 | var result = this.each(function() { 112 | highlight(this, addItems); 113 | }); 114 | for (var i = 0; i < addItems.length; ++i) { 115 | jQuery(addItems[i].parent).before(addItems[i].target); 116 | } 117 | return result; 118 | }; 119 | 120 | /* 121 | * backward compatibility for jQuery.browser 122 | * This will be supported until firefox bug is fixed. 123 | */ 124 | if (!jQuery.browser) { 125 | jQuery.uaMatch = function(ua) { 126 | ua = ua.toLowerCase(); 127 | 128 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 129 | /(webkit)[ \/]([\w.]+)/.exec(ua) || 130 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 131 | /(msie) ([\w.]+)/.exec(ua) || 132 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || 133 | []; 134 | 135 | return { 136 | browser: match[ 1 ] || "", 137 | version: match[ 2 ] || "0" 138 | }; 139 | }; 140 | jQuery.browser = {}; 141 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; 142 | } 143 | 144 | /** 145 | * Small JavaScript module for the documentation. 146 | */ 147 | var Documentation = { 148 | 149 | init : function() { 150 | this.fixFirefoxAnchorBug(); 151 | this.highlightSearchWords(); 152 | this.initIndexTable(); 153 | 154 | }, 155 | 156 | /** 157 | * i18n support 158 | */ 159 | TRANSLATIONS : {}, 160 | PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, 161 | LOCALE : 'unknown', 162 | 163 | // gettext and ngettext don't access this so that the functions 164 | // can safely bound to a different name (_ = Documentation.gettext) 165 | gettext : function(string) { 166 | var translated = Documentation.TRANSLATIONS[string]; 167 | if (typeof translated === 'undefined') 168 | return string; 169 | return (typeof translated === 'string') ? translated : translated[0]; 170 | }, 171 | 172 | ngettext : function(singular, plural, n) { 173 | var translated = Documentation.TRANSLATIONS[singular]; 174 | if (typeof translated === 'undefined') 175 | return (n == 1) ? singular : plural; 176 | return translated[Documentation.PLURALEXPR(n)]; 177 | }, 178 | 179 | addTranslations : function(catalog) { 180 | for (var key in catalog.messages) 181 | this.TRANSLATIONS[key] = catalog.messages[key]; 182 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); 183 | this.LOCALE = catalog.locale; 184 | }, 185 | 186 | /** 187 | * add context elements like header anchor links 188 | */ 189 | addContextElements : function() { 190 | $('div[id] > :header:first').each(function() { 191 | $('\u00B6'). 192 | attr('href', '#' + this.id). 193 | attr('title', _('Permalink to this headline')). 194 | appendTo(this); 195 | }); 196 | $('dt[id]').each(function() { 197 | $('\u00B6'). 198 | attr('href', '#' + this.id). 199 | attr('title', _('Permalink to this definition')). 200 | appendTo(this); 201 | }); 202 | }, 203 | 204 | /** 205 | * workaround a firefox stupidity 206 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 207 | */ 208 | fixFirefoxAnchorBug : function() { 209 | if (document.location.hash && $.browser.mozilla) 210 | window.setTimeout(function() { 211 | document.location.href += ''; 212 | }, 10); 213 | }, 214 | 215 | /** 216 | * highlight the search words provided in the url in the text 217 | */ 218 | highlightSearchWords : function() { 219 | var params = $.getQueryParameters(); 220 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; 221 | if (terms.length) { 222 | var body = $('div.body'); 223 | if (!body.length) { 224 | body = $('body'); 225 | } 226 | window.setTimeout(function() { 227 | $.each(terms, function() { 228 | body.highlightText(this.toLowerCase(), 'highlighted'); 229 | }); 230 | }, 10); 231 | $('') 233 | .appendTo($('#searchbox')); 234 | } 235 | }, 236 | 237 | /** 238 | * init the domain index toggle buttons 239 | */ 240 | initIndexTable : function() { 241 | var togglers = $('img.toggler').click(function() { 242 | var src = $(this).attr('src'); 243 | var idnum = $(this).attr('id').substr(7); 244 | $('tr.cg-' + idnum).toggle(); 245 | if (src.substr(-9) === 'minus.png') 246 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); 247 | else 248 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); 249 | }).css('display', ''); 250 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { 251 | togglers.click(); 252 | } 253 | }, 254 | 255 | /** 256 | * helper function to hide the search marks again 257 | */ 258 | hideSearchWords : function() { 259 | $('#searchbox .highlight-link').fadeOut(300); 260 | $('span.highlighted').removeClass('highlighted'); 261 | }, 262 | 263 | /** 264 | * make the url absolute 265 | */ 266 | makeURL : function(relativeURL) { 267 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; 268 | }, 269 | 270 | /** 271 | * get the current relative url 272 | */ 273 | getCurrentURL : function() { 274 | var path = document.location.pathname; 275 | var parts = path.split(/\//); 276 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { 277 | if (this === '..') 278 | parts.pop(); 279 | }); 280 | var url = parts.join('/'); 281 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1); 282 | }, 283 | 284 | initOnKeyListeners: function() { 285 | $(document).keyup(function(event) { 286 | var activeElementType = document.activeElement.tagName; 287 | // don't navigate when in search box or textarea 288 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { 289 | switch (event.keyCode) { 290 | case 37: // left 291 | var prevHref = $('link[rel="prev"]').prop('href'); 292 | if (prevHref) { 293 | window.location.href = prevHref; 294 | return false; 295 | } 296 | case 39: // right 297 | var nextHref = $('link[rel="next"]').prop('href'); 298 | if (nextHref) { 299 | window.location.href = nextHref; 300 | return false; 301 | } 302 | } 303 | } 304 | }); 305 | } 306 | }; 307 | 308 | // quick alias for translations 309 | _ = Documentation.gettext; 310 | 311 | $(document).ready(function() { 312 | Documentation.init(); 313 | }); -------------------------------------------------------------------------------- /docs/html/_static/underscore.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.3.1 2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 3 | // Underscore is freely distributable under the MIT license. 4 | // Portions of Underscore are inspired or borrowed from Prototype, 5 | // Oliver Steele's Functional, and John Resig's Micro-Templating. 6 | // For all details and documentation: 7 | // http://documentcloud.github.com/underscore 8 | (function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== 9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c, 10 | h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each= 11 | b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a== 12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect= 13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e= 14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= 15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a, 17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}}; 24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments, 25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)}; 26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"}; 27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a), 28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+ 29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]= 30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain= 31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); 32 | -------------------------------------------------------------------------------- /docs/html/like.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Like Features — InstaPy Light 0.1 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 98 | 99 |
100 | 101 | 102 | 108 | 109 | 110 |
111 | 112 |
113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 |
131 | 132 |
    133 | 134 |
  • Docs »
  • 135 | 136 |
  • Like Features
  • 137 | 138 | 139 |
  • 140 | 141 | 142 | View page source 143 | 144 | 145 |
  • 146 | 147 |
148 | 149 | 150 |
151 |
152 |
153 |
154 | 155 |
156 |

Like Features

157 |

Module that handles like features

158 |
159 | 161 |

Check if the Post is Valid/Exists

162 |
163 | 164 |
165 | 167 |

Fetches the number of links specified by amount and returns a list of links

168 |
169 | 170 |
171 | 173 |

Fetches the number of links specified by amount and returns a list of links

174 |
175 | 176 |
177 | 179 |

Fetches the number of links specified by amount and returns a list of links

180 |
181 | 182 |
183 | 185 |

Fetches random number of links from feed and returns a list of links

186 |
187 |
Args:
188 |
189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 |
browser:web driver
amount:?
num_of_search:?
logger:library to log actions
202 |
203 |
Returns:
204 |
links ?
205 |
206 |
207 | 208 |
209 |
210 | app.like.get_tags(browser, url)
211 |

Gets all the tags of the given description in the url

212 |
213 | 214 |
215 |
216 | app.like.like_image(account_id, browser, profile, blacklist, logger)
217 |

Likes opened image

218 |
219 |
Args:
220 |
221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 |
account_id:Instagram Account Id
browser:web driver
username:our username
blacklist:blacklist setup
logger:library to log actions
236 |
237 |
Returns:
238 |
True / False
239 |
240 |
241 | 242 |
243 | 244 | 245 |
246 | 247 |
248 |
249 | 250 | 258 | 259 | 260 |
261 | 262 |
263 |

264 | © Copyright 2018, converge. 265 | 266 |

267 |
268 | Built with Sphinx using a theme provided by Read the Docs. 269 | 270 |
271 | 272 |
273 |
274 | 275 |
276 | 277 |
278 | 279 | 280 | 281 | 282 | 283 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 307 | 308 | 309 | -------------------------------------------------------------------------------- /docs/html/util.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Util Features — InstaPy Light 0.1 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 | 43 | 44 | 97 | 98 |
99 | 100 | 101 | 107 | 108 | 109 |
110 | 111 |
112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 |
130 | 131 |
    132 | 133 |
  • Docs »
  • 134 | 135 |
  • Util Features
  • 136 | 137 | 138 |
  • 139 | 140 | 141 | View page source 142 | 143 | 144 |
  • 145 | 146 |
147 | 148 | 149 |
150 |
151 |
152 |
153 | 154 |
155 |

Util Features

156 |

When we don`t know where to place a feature, this is mamas house

157 |
158 |
159 | app.util.formatNumber(number)
160 |

Receive an unformated number an return a formated number

161 |
162 | 163 |
164 |
165 | app.util.get_account_id(username)
166 |

Return the related account id

167 |
168 |
Args:
169 |
170 | 171 | 172 | 173 | 174 | 175 | 176 |
username:username to be consulted
177 |
178 |
179 |
180 | 181 |
182 |
183 | app.util.get_active_users(browser, username, posts, logger)
184 |

Returns a list with users who liked the latest posts

185 |
186 |
Args:
187 |
188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 |
browser:web driver
username:our username
posts:amount of posts to be verified
logger:library to log actions
201 |
202 |
Returns:
203 |
Active Users based on filter above
204 |
205 |
206 | 207 |
208 |
209 | app.util.is_account_active(browser, profile)
210 |

Check if it`s an active Instagram Account

211 |
212 |
Args:
213 |
214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 |
browser:web driver
profile:profile name to be checked
223 |
224 |
Returns:
225 |
True for active profiles / False for invalid profiles
226 |
227 |
228 | 229 |
230 |
231 | app.util.scroll_bottom(browser, element, range_int)
232 |

Instagram doesn`t load all content once, and we need to scroll the pages 233 | down to load more content

234 |
235 |
Args:
236 |
237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 |
browser:web driver
element:web page element to be scrolled
rand_int:calculates the scrolling limit
248 |
249 |
Returns:
250 |
wtf?
251 |
252 |
253 | 254 |
255 |
256 | app.util.update_activity(action=None)
257 |

Record every Instagram server call (page load, content load, likes, 258 | comments, follows, unfollow).

259 |
260 |

Note

261 |

we need to reorganize this idea

262 |
263 |
264 | 265 |
266 |
267 | app.util.validate_username(browser, username, blacklist, like_by_followers_upper_limit, like_by_followers_lower_limit)
268 |

Check if we can interact with the user

269 |
270 |
Args:
271 |
272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 |
browser:web driver
username:our username
blacklist:blacklist setup
like_by_followers_upper_limit:
 <-
like_by_followers_lower_limit:
 <-
289 |
290 |
291 |
292 |

Note

293 |

are we using it ?

294 |
295 |
296 | 297 |
298 | 299 | 300 |
301 | 302 |
303 |
304 | 305 | 311 | 312 | 313 |
314 | 315 |
316 |

317 | © Copyright 2018, converge. 318 | 319 |

320 |
321 | Built with Sphinx using a theme provided by Read the Docs. 322 | 323 |
324 | 325 |
326 |
327 | 328 |
329 | 330 |
331 | 332 | 333 | 334 | 335 | 336 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 360 | 361 | 362 | -------------------------------------------------------------------------------- /docs/html/blacklist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Blacklist Features — InstaPy Light 0.1 documentation 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 98 | 99 |
100 | 101 | 102 | 108 | 109 | 110 |
111 | 112 |
113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 |
131 | 132 |
    133 | 134 |
  • Docs »
  • 135 | 136 |
  • Blacklist Features
  • 137 | 138 | 139 |
  • 140 | 141 | 142 | View page source 143 | 144 | 145 |
  • 146 | 147 |
148 | 149 | 150 |
151 |
152 |
153 |
154 | 155 |
156 |

Blacklist Features

157 |
158 |
159 | app.blacklist.add_user_to_blacklist(account_id, browser, profile, blacklist, action, logger)
160 |

Adds a profile to user blacklist campaign

161 |
162 |
Args:
163 |
164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 |
account_id:account_id of the logged in username
browser:web driver
profile:profile to be added to blacklist campaign
blacklist:blacklist setup
action:action done by the user (like or follow)
logger:library to log actions.
181 |
182 |
183 |
184 | 185 |
186 |
187 | app.blacklist.get_followed_by_campaign(campaign)
188 |

Get all followed users from a blacklist campaign

189 |
190 |
Args:
191 |
192 | 193 | 194 | 195 | 196 | 197 | 198 |
campaign:blacklist campaign name
199 |
200 |
Returns:
201 |
List of profiles followed by the campaign
202 |
203 |
204 | 205 |
206 |
207 | app.blacklist.get_profiles_from_blacklist_campaign(blacklist, username, logger)
208 |

Returns all users from a blacklist campaign

209 |
210 |
Args:
211 |
212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 |
blacklist:blacklist setup
account_id:username account id
logger:library to log actions
223 |
224 |
Returns:
225 |
list of profile names from the campaign
226 |
227 |
228 | 229 |
230 |
231 | app.blacklist.is_user_in_followed_blacklist(profile, blacklist)
232 |

Check if profile is in blacklist (followed by the blacklist campaign)

233 |
234 |
Args:
235 |
236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 |
profile:profile to be checked
blacklist:blacklist setup
245 |
246 |
Returns:
247 |
True or False
248 |
249 |
250 | 251 |
252 |
253 | app.blacklist.is_user_in_liked_blacklist(profile, blacklist)
254 |

Check if profile is in blacklist (liked by the blacklist campaign)

255 |
256 |
Args:
257 |
258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 |
profile:profile to be checked
blacklist:blacklist setup
267 |
268 |
Returns:
269 |
True or False
270 |
271 |
272 | 273 |
274 |
275 | app.blacklist.mark_as_unfollowed_by_blacklist_campaign(profile, campaign, logger)
276 |

Update database marking the profile as unfollowed by the blacklist campaign

277 |
278 |
Args:
279 |
280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 |
profile:profile to by marked as unfollowed by blacklist campaign
campaign:black campaign name
logger:library to log actions
291 |
292 |
293 |
294 | 295 |
296 | 297 | 298 |
299 | 300 |
301 |
302 | 303 | 311 | 312 | 313 |
314 | 315 |
316 |

317 | © Copyright 2018, converge. 318 | 319 |

320 |
321 | Built with Sphinx using a theme provided by Read the Docs. 322 | 323 |
324 | 325 |
326 |
327 | 328 |
329 | 330 |
331 | 332 | 333 | 334 | 335 | 336 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 360 | 361 | 362 | -------------------------------------------------------------------------------- /docs/html/_static/basic.css: -------------------------------------------------------------------------------- 1 | /* 2 | * basic.css 3 | * ~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- basic theme. 6 | * 7 | * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | /* -- main layout ----------------------------------------------------------- */ 13 | 14 | div.clearer { 15 | clear: both; 16 | } 17 | 18 | /* -- relbar ---------------------------------------------------------------- */ 19 | 20 | div.related { 21 | width: 100%; 22 | font-size: 90%; 23 | } 24 | 25 | div.related h3 { 26 | display: none; 27 | } 28 | 29 | div.related ul { 30 | margin: 0; 31 | padding: 0 0 0 10px; 32 | list-style: none; 33 | } 34 | 35 | div.related li { 36 | display: inline; 37 | } 38 | 39 | div.related li.right { 40 | float: right; 41 | margin-right: 5px; 42 | } 43 | 44 | /* -- sidebar --------------------------------------------------------------- */ 45 | 46 | div.sphinxsidebarwrapper { 47 | padding: 10px 5px 0 10px; 48 | } 49 | 50 | div.sphinxsidebar { 51 | float: left; 52 | width: 230px; 53 | margin-left: -100%; 54 | font-size: 90%; 55 | word-wrap: break-word; 56 | overflow-wrap : break-word; 57 | } 58 | 59 | div.sphinxsidebar ul { 60 | list-style: none; 61 | } 62 | 63 | div.sphinxsidebar ul ul, 64 | div.sphinxsidebar ul.want-points { 65 | margin-left: 20px; 66 | list-style: square; 67 | } 68 | 69 | div.sphinxsidebar ul ul { 70 | margin-top: 0; 71 | margin-bottom: 0; 72 | } 73 | 74 | div.sphinxsidebar form { 75 | margin-top: 10px; 76 | } 77 | 78 | div.sphinxsidebar input { 79 | border: 1px solid #98dbcc; 80 | font-family: sans-serif; 81 | font-size: 1em; 82 | } 83 | 84 | div.sphinxsidebar #searchbox input[type="text"] { 85 | float: left; 86 | width: 80%; 87 | padding: 0.25em; 88 | box-sizing: border-box; 89 | } 90 | 91 | div.sphinxsidebar #searchbox input[type="submit"] { 92 | float: left; 93 | width: 20%; 94 | border-left: none; 95 | padding: 0.25em; 96 | box-sizing: border-box; 97 | } 98 | 99 | 100 | img { 101 | border: 0; 102 | max-width: 100%; 103 | } 104 | 105 | /* -- search page ----------------------------------------------------------- */ 106 | 107 | ul.search { 108 | margin: 10px 0 0 20px; 109 | padding: 0; 110 | } 111 | 112 | ul.search li { 113 | padding: 5px 0 5px 20px; 114 | background-image: url(file.png); 115 | background-repeat: no-repeat; 116 | background-position: 0 7px; 117 | } 118 | 119 | ul.search li a { 120 | font-weight: bold; 121 | } 122 | 123 | ul.search li div.context { 124 | color: #888; 125 | margin: 2px 0 0 30px; 126 | text-align: left; 127 | } 128 | 129 | ul.keywordmatches li.goodmatch a { 130 | font-weight: bold; 131 | } 132 | 133 | /* -- index page ------------------------------------------------------------ */ 134 | 135 | table.contentstable { 136 | width: 90%; 137 | margin-left: auto; 138 | margin-right: auto; 139 | } 140 | 141 | table.contentstable p.biglink { 142 | line-height: 150%; 143 | } 144 | 145 | a.biglink { 146 | font-size: 1.3em; 147 | } 148 | 149 | span.linkdescr { 150 | font-style: italic; 151 | padding-top: 5px; 152 | font-size: 90%; 153 | } 154 | 155 | /* -- general index --------------------------------------------------------- */ 156 | 157 | table.indextable { 158 | width: 100%; 159 | } 160 | 161 | table.indextable td { 162 | text-align: left; 163 | vertical-align: top; 164 | } 165 | 166 | table.indextable ul { 167 | margin-top: 0; 168 | margin-bottom: 0; 169 | list-style-type: none; 170 | } 171 | 172 | table.indextable > tbody > tr > td > ul { 173 | padding-left: 0em; 174 | } 175 | 176 | table.indextable tr.pcap { 177 | height: 10px; 178 | } 179 | 180 | table.indextable tr.cap { 181 | margin-top: 10px; 182 | background-color: #f2f2f2; 183 | } 184 | 185 | img.toggler { 186 | margin-right: 3px; 187 | margin-top: 3px; 188 | cursor: pointer; 189 | } 190 | 191 | div.modindex-jumpbox { 192 | border-top: 1px solid #ddd; 193 | border-bottom: 1px solid #ddd; 194 | margin: 1em 0 1em 0; 195 | padding: 0.4em; 196 | } 197 | 198 | div.genindex-jumpbox { 199 | border-top: 1px solid #ddd; 200 | border-bottom: 1px solid #ddd; 201 | margin: 1em 0 1em 0; 202 | padding: 0.4em; 203 | } 204 | 205 | /* -- domain module index --------------------------------------------------- */ 206 | 207 | table.modindextable td { 208 | padding: 2px; 209 | border-collapse: collapse; 210 | } 211 | 212 | /* -- general body styles --------------------------------------------------- */ 213 | 214 | div.body { 215 | min-width: 450px; 216 | max-width: 800px; 217 | } 218 | 219 | div.body p, div.body dd, div.body li, div.body blockquote { 220 | -moz-hyphens: auto; 221 | -ms-hyphens: auto; 222 | -webkit-hyphens: auto; 223 | hyphens: auto; 224 | } 225 | 226 | a.headerlink { 227 | visibility: hidden; 228 | } 229 | 230 | h1:hover > a.headerlink, 231 | h2:hover > a.headerlink, 232 | h3:hover > a.headerlink, 233 | h4:hover > a.headerlink, 234 | h5:hover > a.headerlink, 235 | h6:hover > a.headerlink, 236 | dt:hover > a.headerlink, 237 | caption:hover > a.headerlink, 238 | p.caption:hover > a.headerlink, 239 | div.code-block-caption:hover > a.headerlink { 240 | visibility: visible; 241 | } 242 | 243 | div.body p.caption { 244 | text-align: inherit; 245 | } 246 | 247 | div.body td { 248 | text-align: left; 249 | } 250 | 251 | .first { 252 | margin-top: 0 !important; 253 | } 254 | 255 | p.rubric { 256 | margin-top: 30px; 257 | font-weight: bold; 258 | } 259 | 260 | img.align-left, .figure.align-left, object.align-left { 261 | clear: left; 262 | float: left; 263 | margin-right: 1em; 264 | } 265 | 266 | img.align-right, .figure.align-right, object.align-right { 267 | clear: right; 268 | float: right; 269 | margin-left: 1em; 270 | } 271 | 272 | img.align-center, .figure.align-center, object.align-center { 273 | display: block; 274 | margin-left: auto; 275 | margin-right: auto; 276 | } 277 | 278 | .align-left { 279 | text-align: left; 280 | } 281 | 282 | .align-center { 283 | text-align: center; 284 | } 285 | 286 | .align-right { 287 | text-align: right; 288 | } 289 | 290 | /* -- sidebars -------------------------------------------------------------- */ 291 | 292 | div.sidebar { 293 | margin: 0 0 0.5em 1em; 294 | border: 1px solid #ddb; 295 | padding: 7px 7px 0 7px; 296 | background-color: #ffe; 297 | width: 40%; 298 | float: right; 299 | } 300 | 301 | p.sidebar-title { 302 | font-weight: bold; 303 | } 304 | 305 | /* -- topics ---------------------------------------------------------------- */ 306 | 307 | div.topic { 308 | border: 1px solid #ccc; 309 | padding: 7px 7px 0 7px; 310 | margin: 10px 0 10px 0; 311 | } 312 | 313 | p.topic-title { 314 | font-size: 1.1em; 315 | font-weight: bold; 316 | margin-top: 10px; 317 | } 318 | 319 | /* -- admonitions ----------------------------------------------------------- */ 320 | 321 | div.admonition { 322 | margin-top: 10px; 323 | margin-bottom: 10px; 324 | padding: 7px; 325 | } 326 | 327 | div.admonition dt { 328 | font-weight: bold; 329 | } 330 | 331 | div.admonition dl { 332 | margin-bottom: 0; 333 | } 334 | 335 | p.admonition-title { 336 | margin: 0px 10px 5px 0px; 337 | font-weight: bold; 338 | } 339 | 340 | div.body p.centered { 341 | text-align: center; 342 | margin-top: 25px; 343 | } 344 | 345 | /* -- tables ---------------------------------------------------------------- */ 346 | 347 | table.docutils { 348 | border: 0; 349 | border-collapse: collapse; 350 | } 351 | 352 | table.align-center { 353 | margin-left: auto; 354 | margin-right: auto; 355 | } 356 | 357 | table caption span.caption-number { 358 | font-style: italic; 359 | } 360 | 361 | table caption span.caption-text { 362 | } 363 | 364 | table.docutils td, table.docutils th { 365 | padding: 1px 8px 1px 5px; 366 | border-top: 0; 367 | border-left: 0; 368 | border-right: 0; 369 | border-bottom: 1px solid #aaa; 370 | } 371 | 372 | table.footnote td, table.footnote th { 373 | border: 0 !important; 374 | } 375 | 376 | th { 377 | text-align: left; 378 | padding-right: 5px; 379 | } 380 | 381 | table.citation { 382 | border-left: solid 1px gray; 383 | margin-left: 1px; 384 | } 385 | 386 | table.citation td { 387 | border-bottom: none; 388 | } 389 | 390 | /* -- figures --------------------------------------------------------------- */ 391 | 392 | div.figure { 393 | margin: 0.5em; 394 | padding: 0.5em; 395 | } 396 | 397 | div.figure p.caption { 398 | padding: 0.3em; 399 | } 400 | 401 | div.figure p.caption span.caption-number { 402 | font-style: italic; 403 | } 404 | 405 | div.figure p.caption span.caption-text { 406 | } 407 | 408 | /* -- field list styles ----------------------------------------------------- */ 409 | 410 | table.field-list td, table.field-list th { 411 | border: 0 !important; 412 | } 413 | 414 | .field-list ul { 415 | margin: 0; 416 | padding-left: 1em; 417 | } 418 | 419 | .field-list p { 420 | margin: 0; 421 | } 422 | 423 | .field-name { 424 | -moz-hyphens: manual; 425 | -ms-hyphens: manual; 426 | -webkit-hyphens: manual; 427 | hyphens: manual; 428 | } 429 | 430 | /* -- other body styles ----------------------------------------------------- */ 431 | 432 | ol.arabic { 433 | list-style: decimal; 434 | } 435 | 436 | ol.loweralpha { 437 | list-style: lower-alpha; 438 | } 439 | 440 | ol.upperalpha { 441 | list-style: upper-alpha; 442 | } 443 | 444 | ol.lowerroman { 445 | list-style: lower-roman; 446 | } 447 | 448 | ol.upperroman { 449 | list-style: upper-roman; 450 | } 451 | 452 | dl { 453 | margin-bottom: 15px; 454 | } 455 | 456 | dd p { 457 | margin-top: 0px; 458 | } 459 | 460 | dd ul, dd table { 461 | margin-bottom: 10px; 462 | } 463 | 464 | dd { 465 | margin-top: 3px; 466 | margin-bottom: 10px; 467 | margin-left: 30px; 468 | } 469 | 470 | dt:target, span.highlighted { 471 | background-color: #fbe54e; 472 | } 473 | 474 | rect.highlighted { 475 | fill: #fbe54e; 476 | } 477 | 478 | dl.glossary dt { 479 | font-weight: bold; 480 | font-size: 1.1em; 481 | } 482 | 483 | .optional { 484 | font-size: 1.3em; 485 | } 486 | 487 | .sig-paren { 488 | font-size: larger; 489 | } 490 | 491 | .versionmodified { 492 | font-style: italic; 493 | } 494 | 495 | .system-message { 496 | background-color: #fda; 497 | padding: 5px; 498 | border: 3px solid red; 499 | } 500 | 501 | .footnote:target { 502 | background-color: #ffa; 503 | } 504 | 505 | .line-block { 506 | display: block; 507 | margin-top: 1em; 508 | margin-bottom: 1em; 509 | } 510 | 511 | .line-block .line-block { 512 | margin-top: 0; 513 | margin-bottom: 0; 514 | margin-left: 1.5em; 515 | } 516 | 517 | .guilabel, .menuselection { 518 | font-family: sans-serif; 519 | } 520 | 521 | .accelerator { 522 | text-decoration: underline; 523 | } 524 | 525 | .classifier { 526 | font-style: oblique; 527 | } 528 | 529 | abbr, acronym { 530 | border-bottom: dotted 1px; 531 | cursor: help; 532 | } 533 | 534 | /* -- code displays --------------------------------------------------------- */ 535 | 536 | pre { 537 | overflow: auto; 538 | overflow-y: hidden; /* fixes display issues on Chrome browsers */ 539 | } 540 | 541 | span.pre { 542 | -moz-hyphens: none; 543 | -ms-hyphens: none; 544 | -webkit-hyphens: none; 545 | hyphens: none; 546 | } 547 | 548 | td.linenos pre { 549 | padding: 5px 0px; 550 | border: 0; 551 | background-color: transparent; 552 | color: #aaa; 553 | } 554 | 555 | table.highlighttable { 556 | margin-left: 0.5em; 557 | } 558 | 559 | table.highlighttable td { 560 | padding: 0 0.5em 0 0.5em; 561 | } 562 | 563 | div.code-block-caption { 564 | padding: 2px 5px; 565 | font-size: small; 566 | } 567 | 568 | div.code-block-caption code { 569 | background-color: transparent; 570 | } 571 | 572 | div.code-block-caption + div > div.highlight > pre { 573 | margin-top: 0; 574 | } 575 | 576 | div.code-block-caption span.caption-number { 577 | padding: 0.1em 0.3em; 578 | font-style: italic; 579 | } 580 | 581 | div.code-block-caption span.caption-text { 582 | } 583 | 584 | div.literal-block-wrapper { 585 | padding: 1em 1em 0; 586 | } 587 | 588 | div.literal-block-wrapper div.highlight { 589 | margin: 0; 590 | } 591 | 592 | code.descname { 593 | background-color: transparent; 594 | font-weight: bold; 595 | font-size: 1.2em; 596 | } 597 | 598 | code.descclassname { 599 | background-color: transparent; 600 | } 601 | 602 | code.xref, a code { 603 | background-color: transparent; 604 | font-weight: bold; 605 | } 606 | 607 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { 608 | background-color: transparent; 609 | } 610 | 611 | .viewcode-link { 612 | float: right; 613 | } 614 | 615 | .viewcode-back { 616 | float: right; 617 | font-family: sans-serif; 618 | } 619 | 620 | div.viewcode-block:target { 621 | margin: -1px -10px; 622 | padding: 0 10px; 623 | } 624 | 625 | /* -- math display ---------------------------------------------------------- */ 626 | 627 | img.math { 628 | vertical-align: middle; 629 | } 630 | 631 | div.body div.math p { 632 | text-align: center; 633 | } 634 | 635 | span.eqno { 636 | float: right; 637 | } 638 | 639 | span.eqno a.headerlink { 640 | position: relative; 641 | left: 0px; 642 | z-index: 1; 643 | } 644 | 645 | div.math:hover a.headerlink { 646 | visibility: visible; 647 | } 648 | 649 | /* -- printout stylesheet --------------------------------------------------- */ 650 | 651 | @media print { 652 | div.document, 653 | div.documentwrapper, 654 | div.bodywrapper { 655 | margin: 0 !important; 656 | width: 100%; 657 | } 658 | 659 | div.sphinxsidebar, 660 | div.related, 661 | div.footer, 662 | #top-link { 663 | display: none; 664 | } 665 | } -------------------------------------------------------------------------------- /docs/html/_static/js/modernizr.min.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.6.2 (Custom Build) | MIT & BSD 2 | * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load 3 | */ 4 | ;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f