Codebase list instaloader / b2764d9
Import upstream version 4.9b1 Kali Janitor 2 years ago
58 changed file(s) with 3029 addition(s) and 1523 deletion(s). Raw diff Collapse all Expand all
1212 (e.g. Instaloader command line)
1313
1414 **Expected behavior**
15 A clear and concise description of what you expected to happen (if not obvious).
15 A clear and concise description of what you expected to happen (even if it seems obvious).
1616
1717 **Error messages and tracebacks**
1818 If applicable, add error messages and tracebacks to help explain your problem.
2323 **Additional context**
2424 Add any other context about the problem here.
2525
26 <!-- please also see https://instaloader.github.io/contributing.html for how to report a bug -->
26 <!--
27 Also see https://instaloader.github.io/contributing.html for how to report a bug.
28
29 Please understand that a bug issue that lacks the required information cannot be
30 processed.
31 -->
55 ---
66
77 **Provide us a use case of the feature**
8 How could the user invoke the new function? Which problem would it solve? If new information is obtained, how would it be further processed?
8 How could the user invoke the new function? Which problem would it solve?
9 If new information is obtained, how would it be further processed?
910
1011 **Describe the solution you'd like**
1112 A clear and concise description of what you want to happen.
1213
1314 **Describe alternatives you've considered**
1415 A clear and concise description of any alternative solutions or features you've considered.
16 How do you achieve the here-described goal without the feature you are requesting?
1517
16 **If the feature request is accepted, would you be willing to submit a PR?**
18 **If the feature request is accepted, would you be willing to submit a pull request?**
1719 Yes / No
1820 <!-- Help can be provided if you need assistance submitting a PR -->
1921
2022 **Additional context**
2123 Add any other context about the feature request here.
2224
23 <!-- please also see https://instaloader.github.io/contributing.html for how to suggest a feature -->
25 <!--
26 Also see https://instaloader.github.io/contributing.html for how to suggest a feature.
27
28 Please understand that a feature suggestion issue that lacks the required information cannot be
29 processed.
30 -->
66
77 Your question here...
88
9 <!-- Please see our documentation: https://instaloader.github.io/ -->
9 <!--
10 People will be better able and more motivated to provide help if your question
1011
11 <!-- Basic questions regarding Instaloader's usage might be more appropriate to ask on Stack Overflow -->
12 - has a concise and meaningful title,
13 - is not covered by the documentation: https://instaloader.github.io/,
14 - is actually related to Instaloader (this is not a Python help forum),
15 - has not already been answered here or on other sites such as Stack Overflow: https://stackoverflow.com/questions/tagged/instaloader,
16 - is written in a polite and welcoming tone.
17 -->
0 github: [aandergr]
1 custom: "https://instaloader.github.io/sponsors.html"
00
11
22 <!--
3 Please describe:
3 Thanks for your willingness to contribute to Instaloader! Please briefly
4 describe
45
56 - A motivation for this change, e.g.
67 - Fixes # .
77 runs-on: ubuntu-latest
88 strategy:
99 matrix:
10 python-version: [3.8]
10 python-version: ["3.8", "3.9", "3.10"]
1111 steps:
1212 - name: Checkout Instaloader Repository
1313 uses: actions/checkout@v2
1919 python-version: ${{ matrix.python-version }}
2020 - name: Install Dependencies
2121 run: |
22 python -m pip install pipenv==2020.6.2
22 python -m pip install pipenv==2021.5.29
2323 pipenv sync --dev
2424 - name: PyLint
2525 run: pipenv run pylint instaloader
2626 - name: MyPy
2727 run: pipenv run mypy -m instaloader
2828 - name: Build Documentation
29 if: matrix.python-version == '3.8'
2930 run: pipenv run make -C docs html SPHINXOPTS="-W -n"
2929 stale-pr-label: 'stale'
3030 exempt-issue-label: 'leave open'
3131 exempt-pr-label: 'leave open'
32 days-before-stale: 90
32 days-before-stale: 135
3333 days-before-close: 14
99 - name: Checkout Instaloader repository
1010 uses: actions/checkout@v2
1111 - name: Setup Python
12 uses: actions/setup-python@v1
12 uses: actions/setup-python@v2
1313 with:
14 python-version: 3.8
14 python-version: "3.9"
1515 architecture: x64
1616 - name: Get the tagged version
1717 id: get_version
00 dist: xenial
11 language: python
22 python:
3 - "3.5"
43 - "3.6"
54 - "3.7"
65 install:
55 - Alexander Graf (@aandergr)
66 - André Koch-Kramer (@Thammus)
77 - Lars Lindqvist (@e5150)
8 - ... and many more, see https://github.com/instaloader/instaloader/graphs/contributors
0
1 # Contributor Covenant Code of Conduct
2
3 ## Our Pledge
4
5 We as members, contributors, and leaders pledge to make participation in our
6 community a harassment-free experience for everyone, regardless of age, body
7 size, visible or invisible disability, ethnicity, sex characteristics, gender
8 identity and expression, level of experience, education, socio-economic status,
9 nationality, personal appearance, race, religion, or sexual identity
10 and orientation.
11
12 We pledge to act and interact in ways that contribute to an open, welcoming,
13 diverse, inclusive, and healthy community.
14
15 ## Our Standards
16
17 Examples of behavior that contributes to a positive environment for our
18 community include:
19
20 * Demonstrating empathy and kindness toward other people
21 * Being respectful of differing opinions, viewpoints, and experiences
22 * Giving and gracefully accepting constructive feedback
23 * Accepting responsibility and apologizing to those affected by our mistakes,
24 and learning from the experience
25 * Focusing on what is best not just for us as individuals, but for the
26 overall community
27
28 Examples of unacceptable behavior include:
29
30 * The use of sexualized language or imagery, and sexual attention or
31 advances of any kind
32 * Trolling, insulting or derogatory comments, and personal or political attacks
33 * Public or private harassment
34 * Publishing others' private information, such as a physical or email
35 address, without their explicit permission
36 * Other conduct which could reasonably be considered inappropriate in a
37 professional setting
38
39 ## Enforcement Responsibilities
40
41 Community leaders are responsible for clarifying and enforcing our standards of
42 acceptable behavior and will take appropriate and fair corrective action in
43 response to any behavior that they deem inappropriate, threatening, offensive,
44 or harmful.
45
46 Community leaders have the right and responsibility to remove, edit, or reject
47 comments, commits, code, wiki edits, issues, and other contributions that are
48 not aligned to this Code of Conduct, and will communicate reasons for moderation
49 decisions when appropriate.
50
51 ## Scope
52
53 This Code of Conduct applies within all community spaces, and also applies when
54 an individual is officially representing the community in public spaces.
55 Examples of representing our community include using an official e-mail address,
56 posting via an official social media account, or acting as an appointed
57 representative at an online or offline event.
58
59 ## Enforcement
60
61 Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 reported to the community leaders responsible for enforcement by opening an
63 issue or contacting one or more of the project maintainers.
64
65 All complaints will be reviewed and investigated promptly and fairly.
66
67 All community leaders are obligated to respect the privacy and security of the
68 reporter of any incident.
69
70 ## Enforcement Guidelines
71
72 Community leaders will follow these Community Impact Guidelines in determining
73 the consequences for any action they deem in violation of this Code of Conduct:
74
75 ### 1. Correction
76
77 **Community Impact**: Use of inappropriate language or other behavior deemed
78 unprofessional or unwelcome in the community.
79
80 **Consequence**: A private, written warning from community leaders, providing
81 clarity around the nature of the violation and an explanation of why the
82 behavior was inappropriate. A public apology may be requested.
83
84 ### 2. Warning
85
86 **Community Impact**: A violation through a single incident or series
87 of actions.
88
89 **Consequence**: A warning with consequences for continued behavior. No
90 interaction with the people involved, including unsolicited interaction with
91 those enforcing the Code of Conduct, for a specified period of time. This
92 includes avoiding interactions in community spaces as well as external channels
93 like social media. Violating these terms may lead to a temporary or
94 permanent ban.
95
96 ### 3. Temporary Ban
97
98 **Community Impact**: A serious violation of community standards, including
99 sustained inappropriate behavior.
100
101 **Consequence**: A temporary ban from any sort of interaction or public
102 communication with the community for a specified period of time. No public or
103 private interaction with the people involved, including unsolicited interaction
104 with those enforcing the Code of Conduct, is allowed during this period.
105 Violating these terms may lead to a permanent ban.
106
107 ### 4. Permanent Ban
108
109 **Community Impact**: Demonstrating a pattern of violation of community
110 standards, including sustained inappropriate behavior, harassment of an
111 individual, or aggression toward or disparagement of classes of individuals.
112
113 **Consequence**: A permanent ban from any sort of public interaction within
114 the community.
115
116 ## Attribution
117
118 This Code of Conduct is adapted from the [Contributor Covenant][homepage],
119 version 2.0, available at
120 [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
121
122 Community Impact Guidelines were inspired by
123 [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
124
125 For answers to common questions about this code of conduct, see the FAQ at
126 [https://www.contributor-covenant.org/faq][FAQ]. Translations are available
127 at [https://www.contributor-covenant.org/translations][translations].
128
129 [homepage]: https://www.contributor-covenant.org
130 [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
131 [Mozilla CoC]: https://github.com/mozilla/diversity
132 [FAQ]: https://www.contributor-covenant.org/faq
133 [translations]: https://www.contributor-covenant.org/translations
134
00 The MIT License (MIT)
11
2 Copyright (c) 2016-2019 Alexander Graf and André Koch-Kramer.
2 Copyright (c) 2016-2020 Alexander Graf and André Koch-Kramer.
33
44 Permission is hereby granted, free of charge, to any person obtaining a copy
55 of this software and associated documentation files (the "Software"), to deal
55 [dev-packages]
66 pylint = "*"
77 mypy = "*"
8 sphinx = "*"
8 sphinx = "~=2.3"
99 pyinstaller = "*"
1010 pefile = "*"
1111 pywin32-ctypes = "*"
1212 psutil = "*"
13 typing-extensions = "*"
14 types-requests = "*"
15 typed-ast = "*"
1316
1417 [packages]
1518 requests = "*"
00 {
11 "_meta": {
22 "hash": {
3 "sha256": "33408a60fda1a56bf680462fad21643ae0159bc13f3b85d8f10ebf3eef7d8725"
3 "sha256": "4ea11d3dd7ae0070a8745cf21960210a09834ca21f47905fd3fab20ea68c6d3b"
44 },
55 "pipfile-spec": 6,
66 "requires": {},
1515 "default": {
1616 "certifi": {
1717 "hashes": [
18 "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
19 "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
20 ],
21 "version": "==2019.11.28"
22 },
23 "chardet": {
24 "hashes": [
25 "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
26 "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
27 ],
28 "version": "==3.0.4"
18 "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee",
19 "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"
20 ],
21 "version": "==2021.5.30"
22 },
23 "charset-normalizer": {
24 "hashes": [
25 "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b",
26 "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"
27 ],
28 "markers": "python_version >= '3'",
29 "version": "==2.0.4"
2930 },
3031 "idna": {
3132 "hashes": [
32 "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
33 "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
34 ],
35 "version": "==2.8"
33 "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
34 "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
35 ],
36 "markers": "python_version >= '3'",
37 "version": "==3.2"
3638 },
3739 "requests": {
3840 "hashes": [
39 "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
40 "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
41 ],
42 "index": "pypi",
43 "version": "==2.22.0"
41 "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24",
42 "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"
43 ],
44 "index": "pypi",
45 "version": "==2.26.0"
4446 },
4547 "urllib3": {
4648 "hashes": [
47 "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
48 "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
49 ],
50 "version": "==1.25.8"
49 "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4",
50 "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"
51 ],
52 "version": "==1.26.6"
5153 }
5254 },
5355 "develop": {
6769 },
6870 "astroid": {
6971 "hashes": [
70 "sha256:71ea07f44df9568a75d0f354c49143a4575d90645e9fead6dfb52c26a85ed13a",
71 "sha256:840947ebfa8b58f318d42301cf8c0a20fd794a33b61cc4638e28e9e61ba32f42"
72 ],
73 "version": "==2.3.3"
72 "sha256:3975a0bd5373bdce166e60c851cfcbaf21ee96de80ec518c1f4cb3e94c3fb334",
73 "sha256:ab7f36e8a78b8e54a62028ba6beef7561db4cdb6f2a5009ecc44a6f42b5697ef"
74 ],
75 "version": "==2.6.6"
7476 },
7577 "babel": {
7678 "hashes": [
77 "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38",
78 "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4"
79 ],
80 "version": "==2.8.0"
79 "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9",
80 "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"
81 ],
82 "version": "==2.9.1"
8183 },
8284 "certifi": {
8385 "hashes": [
84 "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
85 "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
86 ],
87 "version": "==2019.11.28"
88 },
89 "chardet": {
90 "hashes": [
91 "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
92 "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
93 ],
94 "version": "==3.0.4"
86 "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee",
87 "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"
88 ],
89 "version": "==2021.5.30"
90 },
91 "charset-normalizer": {
92 "hashes": [
93 "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b",
94 "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"
95 ],
96 "markers": "python_version >= '3'",
97 "version": "==2.0.4"
9598 },
9699 "docutils": {
97100 "hashes": [
98 "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af",
99 "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"
100 ],
101 "version": "==0.16"
101 "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125",
102 "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"
103 ],
104 "version": "==0.17.1"
102105 },
103106 "future": {
104107 "hashes": [
108111 },
109112 "idna": {
110113 "hashes": [
111 "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
112 "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
113 ],
114 "version": "==2.8"
114 "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
115 "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
116 ],
117 "markers": "python_version >= '3'",
118 "version": "==3.2"
115119 },
116120 "imagesize": {
117121 "hashes": [
122126 },
123127 "isort": {
124128 "hashes": [
125 "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1",
126 "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"
127 ],
128 "version": "==4.3.21"
129 "sha256:9c2ea1e62d871267b78307fe511c0838ba0da28698c5732d54e2790bf3ba9899",
130 "sha256:e17d6e2b81095c9db0a03a8025a957f334d6ea30b26f9ec70805411e5c7c81f2"
131 ],
132 "version": "==5.9.3"
129133 },
130134 "jinja2": {
131135 "hashes": [
132 "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250",
133 "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"
134 ],
135 "version": "==2.11.1"
136 "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4",
137 "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"
138 ],
139 "version": "==3.0.1"
136140 },
137141 "lazy-object-proxy": {
138142 "hashes": [
139 "sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d",
140 "sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449",
141 "sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08",
142 "sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a",
143 "sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50",
144 "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd",
145 "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239",
146 "sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb",
147 "sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea",
148 "sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e",
149 "sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156",
150 "sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142",
151 "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442",
152 "sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62",
153 "sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db",
154 "sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531",
155 "sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383",
156 "sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a",
157 "sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357",
158 "sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4",
159 "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"
160 ],
161 "version": "==1.4.3"
143 "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653",
144 "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61",
145 "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2",
146 "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837",
147 "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3",
148 "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43",
149 "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726",
150 "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3",
151 "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587",
152 "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8",
153 "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a",
154 "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd",
155 "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f",
156 "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad",
157 "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4",
158 "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b",
159 "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf",
160 "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981",
161 "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741",
162 "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e",
163 "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93",
164 "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b"
165 ],
166 "version": "==1.6.0"
162167 },
163168 "markupsafe": {
164169 "hashes": [
165 "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
166 "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
167 "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
168 "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
169 "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
170 "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
171 "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
172 "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
173 "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
174 "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
175 "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
176 "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
177 "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
178 "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
179 "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
180 "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
181 "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
182 "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
183 "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
184 "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
185 "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
186 "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
187 "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
188 "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
189 "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
190 "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
191 "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
192 "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
193 "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
194 "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
195 "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
196 "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
197 "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
198 ],
199 "version": "==1.1.1"
170 "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
171 "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
172 "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
173 "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
174 "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
175 "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
176 "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
177 "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
178 "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
179 "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
180 "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
181 "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
182 "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
183 "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
184 "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
185 "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
186 "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
187 "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
188 "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
189 "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
190 "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
191 "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
192 "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
193 "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
194 "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
195 "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
196 "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
197 "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
198 "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
199 "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
200 "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
201 "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
202 "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
203 "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
204 ],
205 "version": "==2.0.1"
200206 },
201207 "mccabe": {
202208 "hashes": [
207213 },
208214 "mypy": {
209215 "hashes": [
210 "sha256:0a9a45157e532da06fe56adcfef8a74629566b607fa2c1ac0122d1ff995c748a",
211 "sha256:2c35cae79ceb20d47facfad51f952df16c2ae9f45db6cb38405a3da1cf8fc0a7",
212 "sha256:4b9365ade157794cef9685791032521233729cb00ce76b0ddc78749abea463d2",
213 "sha256:53ea810ae3f83f9c9b452582261ea859828a9ed666f2e1ca840300b69322c474",
214 "sha256:634aef60b4ff0f650d3e59d4374626ca6153fcaff96ec075b215b568e6ee3cb0",
215 "sha256:7e396ce53cacd5596ff6d191b47ab0ea18f8e0ec04e15d69728d530e86d4c217",
216 "sha256:7eadc91af8270455e0d73565b8964da1642fe226665dd5c9560067cd64d56749",
217 "sha256:7f672d02fffcbace4db2b05369142e0506cdcde20cea0e07c7c2171c4fd11dd6",
218 "sha256:85baab8d74ec601e86134afe2bcccd87820f79d2f8d5798c889507d1088287bf",
219 "sha256:87c556fb85d709dacd4b4cb6167eecc5bbb4f0a9864b69136a0d4640fdc76a36",
220 "sha256:a6bd44efee4dc8c3324c13785a9dc3519b3ee3a92cada42d2b57762b7053b49b",
221 "sha256:c6d27bd20c3ba60d5b02f20bd28e20091d6286a699174dfad515636cb09b5a72",
222 "sha256:e2bb577d10d09a2d8822a042a23b8d62bc3b269667c9eb8e60a6edfa000211b1",
223 "sha256:f97a605d7c8bc2c6d1172c2f0d5a65b24142e11a58de689046e62c2d632ca8c1"
224 ],
225 "index": "pypi",
226 "version": "==0.761"
216 "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9",
217 "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a",
218 "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9",
219 "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e",
220 "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2",
221 "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212",
222 "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b",
223 "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885",
224 "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150",
225 "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703",
226 "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072",
227 "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457",
228 "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e",
229 "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0",
230 "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb",
231 "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97",
232 "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8",
233 "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811",
234 "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6",
235 "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de",
236 "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504",
237 "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921",
238 "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"
239 ],
240 "index": "pypi",
241 "version": "==0.910"
227242 },
228243 "mypy-extensions": {
229244 "hashes": [
234249 },
235250 "packaging": {
236251 "hashes": [
237 "sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73",
238 "sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334"
239 ],
240 "version": "==20.1"
252 "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7",
253 "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"
254 ],
255 "version": "==21.0"
241256 },
242257 "pefile": {
243258 "hashes": [
244 "sha256:a5d6e8305c6b210849b47a6174ddf9c452b2888340b8177874b862ba6c207645"
245 ],
246 "index": "pypi",
247 "version": "==2019.4.18"
259 "sha256:ed79b2353daa58421459abf4d685953bde0adf9f6e188944f97ba9795f100246"
260 ],
261 "index": "pypi",
262 "version": "==2021.5.24"
248263 },
249264 "psutil": {
250265 "hashes": [
251 "sha256:094f899ac3ef72422b7e00411b4ed174e3c5a2e04c267db6643937ddba67a05b",
252 "sha256:10b7f75cc8bd676cfc6fa40cd7d5c25b3f45a0e06d43becd7c2d2871cbb5e806",
253 "sha256:1b1575240ca9a90b437e5a40db662acd87bbf181f6aa02f0204978737b913c6b",
254 "sha256:21231ef1c1a89728e29b98a885b8e0a8e00d09018f6da5cdc1f43f988471a995",
255 "sha256:28f771129bfee9fc6b63d83a15d857663bbdcae3828e1cb926e91320a9b5b5cd",
256 "sha256:70387772f84fa5c3bb6a106915a2445e20ac8f9821c5914d7cbde148f4d7ff73",
257 "sha256:b560f5cd86cf8df7bcd258a851ca1ad98f0d5b8b98748e877a0aec4e9032b465",
258 "sha256:b74b43fecce384a57094a83d2778cdfc2e2d9a6afaadd1ebecb2e75e0d34e10d",
259 "sha256:e85f727ffb21539849e6012f47b12f6dd4c44965e56591d8dec6e8bc9ab96f4a",
260 "sha256:fd2e09bb593ad9bdd7429e779699d2d47c1268cbde4dda95fcd1bd17544a0217",
261 "sha256:ffad8eb2ac614518bbe3c0b8eb9dffdb3a8d2e3a7d5da51c5b974fb723a5c5aa"
262 ],
263 "index": "pypi",
264 "version": "==5.6.7"
266 "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64",
267 "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131",
268 "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c",
269 "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6",
270 "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023",
271 "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df",
272 "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394",
273 "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4",
274 "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b",
275 "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2",
276 "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d",
277 "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65",
278 "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d",
279 "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef",
280 "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7",
281 "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60",
282 "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6",
283 "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8",
284 "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b",
285 "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d",
286 "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac",
287 "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935",
288 "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d",
289 "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28",
290 "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876",
291 "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0",
292 "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3",
293 "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563"
294 ],
295 "index": "pypi",
296 "version": "==5.8.0"
265297 },
266298 "pygments": {
267299 "hashes": [
268 "sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b",
269 "sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe"
270 ],
271 "version": "==2.5.2"
300 "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f",
301 "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"
302 ],
303 "version": "==2.9.0"
272304 },
273305 "pyinstaller": {
274306 "hashes": [
275 "sha256:3730fa80d088f8bb7084d32480eb87cbb4ddb64123363763cf8f2a1378c1c4b7"
276 ],
277 "index": "pypi",
278 "version": "==3.6"
307 "sha256:30733baaf8971902286a0ddf77e5499ac5f7bf8e7c39163e83d4f8c696ef265e",
308 "sha256:4d848cd782ee0893d7ad9fe2bfe535206a79f0b6760cecc5f2add831258b9322",
309 "sha256:8f747b190e6ad30e2d2fd5da9a64636f61aac8c038c0b7f685efa92c782ea14f",
310 "sha256:aae456205c68355f9597411090576bb31b614e53976b4c102d072bbe5db8392a",
311 "sha256:c587da8f521a7ce1b9efb4e3d0117cd63c92dc6cedff24590aeef89372f53012",
312 "sha256:ecc2baadeeefd2b6fbf39d13c65d4aa603afdda1c6aaaebc4577ba72893fee9e",
313 "sha256:fed9f5e4802769a416a8f2ca171c6be961d1861cc05a0b71d20dfe05423137e9"
314 ],
315 "index": "pypi",
316 "version": "==4.5.1"
317 },
318 "pyinstaller-hooks-contrib": {
319 "hashes": [
320 "sha256:57964f93eb69255c49159ffdf052aae893feed223b0f69773dfd010ca6c569d9",
321 "sha256:7f5d0689b30da3092149fc536a835a94045ac8c9f0e6dfb23ac171890f5ea8f2"
322 ],
323 "version": "==2021.2"
279324 },
280325 "pylint": {
281326 "hashes": [
282 "sha256:3db5468ad013380e987410a8d6956226963aed94ecb5f9d3a28acca6d9ac36cd",
283 "sha256:886e6afc935ea2590b462664b161ca9a5e40168ea99e5300935f6591ad467df4"
284 ],
285 "index": "pypi",
286 "version": "==2.4.4"
327 "sha256:2e1a0eb2e8ab41d6b5dbada87f066492bb1557b12b76c47c2ee8aa8a11186594",
328 "sha256:8b838c8983ee1904b2de66cce9d0b96649a91901350e956d78f289c3bc87b48e"
329 ],
330 "index": "pypi",
331 "version": "==2.9.6"
287332 },
288333 "pyparsing": {
289334 "hashes": [
290 "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f",
291 "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"
292 ],
293 "version": "==2.4.6"
335 "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
336 "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
337 ],
338 "version": "==2.4.7"
294339 },
295340 "pytz": {
296341 "hashes": [
297 "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
298 "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"
299 ],
300 "version": "==2019.3"
342 "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
343 "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
344 ],
345 "version": "==2021.1"
301346 },
302347 "pywin32-ctypes": {
303348 "hashes": [
309354 },
310355 "requests": {
311356 "hashes": [
312 "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
313 "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
314 ],
315 "index": "pypi",
316 "version": "==2.22.0"
317 },
318 "six": {
319 "hashes": [
320 "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
321 "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
322 ],
323 "version": "==1.14.0"
357 "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24",
358 "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"
359 ],
360 "index": "pypi",
361 "version": "==2.26.0"
324362 },
325363 "snowballstemmer": {
326364 "hashes": [
327 "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0",
328 "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"
365 "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2",
366 "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"
367 ],
368 "version": "==2.1.0"
369 },
370 "sphinx": {
371 "hashes": [
372 "sha256:b4c750d546ab6d7e05bdff6ac24db8ae3e8b8253a3569b754e445110a0a12b66",
373 "sha256:fc312670b56cb54920d6cc2ced455a22a547910de10b3142276495ced49231cb"
374 ],
375 "index": "pypi",
376 "version": "==2.4.4"
377 },
378 "sphinxcontrib-applehelp": {
379 "hashes": [
380 "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a",
381 "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"
382 ],
383 "version": "==1.0.2"
384 },
385 "sphinxcontrib-devhelp": {
386 "hashes": [
387 "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e",
388 "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"
389 ],
390 "version": "==1.0.2"
391 },
392 "sphinxcontrib-htmlhelp": {
393 "hashes": [
394 "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07",
395 "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"
329396 ],
330397 "version": "==2.0.0"
331 },
332 "sphinx": {
333 "hashes": [
334 "sha256:298537cb3234578b2d954ff18c5608468229e116a9757af3b831c2b2b4819159",
335 "sha256:e6e766b74f85f37a5f3e0773a1e1be8db3fcb799deb58ca6d18b70b0b44542a5"
336 ],
337 "index": "pypi",
338 "version": "==2.3.1"
339 },
340 "sphinxcontrib-applehelp": {
341 "hashes": [
342 "sha256:edaa0ab2b2bc74403149cb0209d6775c96de797dfd5b5e2a71981309efab3897",
343 "sha256:fb8dee85af95e5c30c91f10e7eb3c8967308518e0f7488a2828ef7bc191d0d5d"
344 ],
345 "version": "==1.0.1"
346 },
347 "sphinxcontrib-devhelp": {
348 "hashes": [
349 "sha256:6c64b077937330a9128a4da74586e8c2130262f014689b4b89e2d08ee7294a34",
350 "sha256:9512ecb00a2b0821a146736b39f7aeb90759834b07e81e8cc23a9c70bacb9981"
351 ],
352 "version": "==1.0.1"
353 },
354 "sphinxcontrib-htmlhelp": {
355 "hashes": [
356 "sha256:4670f99f8951bd78cd4ad2ab962f798f5618b17675c35c5ac3b2132a14ea8422",
357 "sha256:d4fd39a65a625c9df86d7fa8a2d9f3cd8299a3a4b15db63b50aac9e161d8eff7"
358 ],
359 "version": "==1.0.2"
360398 },
361399 "sphinxcontrib-jsmath": {
362400 "hashes": [
367405 },
368406 "sphinxcontrib-qthelp": {
369407 "hashes": [
370 "sha256:513049b93031beb1f57d4daea74068a4feb77aa5630f856fcff2e50de14e9a20",
371 "sha256:79465ce11ae5694ff165becda529a600c754f4bc459778778c7017374d4d406f"
372 ],
373 "version": "==1.0.2"
408 "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72",
409 "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"
410 ],
411 "version": "==1.0.3"
374412 },
375413 "sphinxcontrib-serializinghtml": {
376414 "hashes": [
377 "sha256:c0efb33f8052c04fd7a26c0a07f1678e8512e0faec19f4aa8f2473a8b81d5227",
378 "sha256:db6615af393650bf1151a6cd39120c29abaf93cc60db8c48eb2dddbfdc3a9768"
379 ],
380 "version": "==1.1.3"
415 "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd",
416 "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"
417 ],
418 "version": "==1.1.5"
419 },
420 "toml": {
421 "hashes": [
422 "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
423 "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
424 ],
425 "version": "==0.10.2"
381426 },
382427 "typed-ast": {
383428 "hashes": [
384 "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
385 "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
386 "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
387 "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
388 "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
389 "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
390 "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
391 "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
392 "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
393 "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
394 "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
395 "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
396 "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
397 "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
398 "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
399 "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
400 "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
401 "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
402 "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
403 "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
404 "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
405 ],
406 "version": "==1.4.1"
429 "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace",
430 "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff",
431 "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266",
432 "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528",
433 "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6",
434 "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808",
435 "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4",
436 "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363",
437 "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341",
438 "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04",
439 "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41",
440 "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e",
441 "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3",
442 "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899",
443 "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805",
444 "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c",
445 "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c",
446 "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39",
447 "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a",
448 "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3",
449 "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7",
450 "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f",
451 "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075",
452 "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0",
453 "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40",
454 "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428",
455 "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927",
456 "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3",
457 "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f",
458 "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"
459 ],
460 "index": "pypi",
461 "version": "==1.4.3"
462 },
463 "types-requests": {
464 "hashes": [
465 "sha256:a5a305b43ea57bf64d6731f89816946a405b591eff6de28d4c0fd58422cee779",
466 "sha256:e21541c0f55c066c491a639309159556dd8c5833e49fcde929c4c47bdb0002ee"
467 ],
468 "index": "pypi",
469 "version": "==2.25.6"
407470 },
408471 "typing-extensions": {
409472 "hashes": [
410 "sha256:091ecc894d5e908ac75209f10d5b4f118fbdb2eb1ede6a63544054bb1edb41f2",
411 "sha256:910f4656f54de5993ad9304959ce9bb903f90aadc7c67a0bef07e678014e892d",
412 "sha256:cf8b63fedea4d89bab840ecbb93e75578af28f76f66c35889bd7065f5af88575"
413 ],
414 "version": "==3.7.4.1"
473 "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
474 "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
475 "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
476 ],
477 "index": "pypi",
478 "version": "==3.10.0.0"
415479 },
416480 "urllib3": {
417481 "hashes": [
418 "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
419 "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
420 ],
421 "version": "==1.25.8"
482 "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4",
483 "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"
484 ],
485 "version": "==1.26.6"
422486 },
423487 "wrapt": {
424488 "hashes": [
425 "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1"
426 ],
427 "version": "==1.11.2"
489 "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"
490 ],
491 "version": "==1.12.1"
428492 }
429493 }
430494 }
2626 :alt: Arch User Repository Package
2727 :target: https://aur.archlinux.org/packages/instaloader/
2828
29 .. |downloads| image:: https://img.shields.io/pypi/dm/instaloader.svg
29 .. |downloads| image:: https://pepy.tech/badge/instaloader/month
3030 :alt: PyPI Download Count
31 :target: https://pepy.tech/project/instaloader
3132
3233 .. badges-end
3334
4849 directory accordingly,
4950
5051 - allows **fine-grained customization** of filters and where to store
51 downloaded media.
52 downloaded media,
53
54 - automatically **resumes previously-interrupted** download iterations.
5255
5356 ::
5457
8083 instaloader --fast-update profile [profile ...]
8184
8285 If ``--fast-update`` is given, Instaloader stops when arriving at the
83 first already-downloaded picture. When updating profiles, Instaloader
86 first already-downloaded picture.
87
88 Alternatively, you can use ``--latest-stamps`` to have Instaloader store
89 the time each profile was last downloaded and only download newer media:
90
91 ::
92
93 instaloader --latest-stamps -- profile [profile ...]
94
95 With this option it's possible to move or delete downloaded media and still keep
96 the archive updated.
97
98 When updating profiles, Instaloader
8499 automatically **detects profile name changes** and renames the target directory
85100 accordingly.
86101
98113
99114 `Instaloader Documentation <https://instaloader.github.io/basic-usage.html>`__
100115
116 Contributing
117 ------------
118
119 As an open source project, Instaloader heavily depends on the contributions from
120 its community. See
121 `contributing <https://instaloader.github.io/contributing.html>`__
122 for how you may help Instaloader to become an even greater tool.
123
124 Supporters
125 ----------
126
127 .. current-sponsors-start
128
129 See `Alex' GitHub Sponsors <https://github.com/sponsors/aandergr>`__ page for
130 how you can sponsor the development of Instaloader!
131
132 .. current-sponsors-end
133
134 It is a pleasure for us to share our Instaloader to the world, and we are proud
135 to have attracted such an active and motivating community, with so many users
136 who share their suggestions and ideas with us. Buying a community-sponsored beer
137 or coffee from time to time is very likely to further raise our passion for the
138 development of Instaloader.
139
140 | For Donations, we provide GitHub Sponsors page, a PayPal.Me link and a Bitcoin address.
141 | GitHub Sponsors: `Sponsor @aandergr on GitHub Sponsors <https://github.com/sponsors/aandergr>`__
142 | PayPal: `PayPal.me/aandergr <https://www.paypal.me/aandergr>`__
143 | BTC: 1Nst4LoadeYzrKjJ1DX9CpbLXBYE9RKLwY
101144
102145 Disclaimer
103146 ----------
110153 Instaloader is licensed under an MIT license. Refer to ``LICENSE`` file for more information.
111154
112155 .. disclaimer-end
113
114 Contributing
115 ------------
116
117 As an open source project, Instaloader heavily depends on the contributions from
118 its community. See
119 `contributing <https://instaloader.github.io/contributing.html>`__
120 for how you may help Instaloader to become an even greater tool.
121
122 It is a pleasure for us to share our Instaloader to the world, and we are proud
123 to have attracted such an active and motivating community, with so many users
124 who share their suggestions and ideas with us. Buying a community-sponsored beer
125 or coffee from time to time is very likely to further raise our passion for the
126 development of Instaloader.
127
128 | For Donations, we provide a PayPal.Me link and a Bitcoin address.
129 | PayPal: `PayPal.me/aandergr <https://www.paypal.me/aandergr>`__
130 | BTC: 1Nst4LoadeYzrKjJ1DX9CpbLXBYE9RKLwY
55 arch = any
66 license = MIT
77 makedepends = python-setuptools
8 depends = python>=3.5
8 depends = python>=3.6
99 depends = python-requests>=2.4
1010 options = !emptydirs
1111 source = instaloader-{{version}}.tar.gz::https://codeload.github.com/instaloader/instaloader/tar.gz/v{{version}}
77 url="https://instaloader.github.io/"
88 license=('MIT')
99 groups=()
10 depends=('python>=3.5' 'python-requests>=2.4')
10 depends=('python>=3.6' 'python-requests>=2.4')
1111 makedepends=('python-setuptools')
1212 options=('!emptydirs')
1313 source=($pkgname-$pkgver.tar.gz::https://codeload.github.com/instaloader/instaloader/tar.gz/v$pkgver)
1616 def __main():
1717 with contextlib.suppress(AttributeError, psutil.Error):
1818 if psutil.Process().parent().parent().name() == "explorer.exe":
19 subprocess.Popen("powershell -NoExit -Command \\\"& {0}\\\"".format(sys.argv[0]))
19 subprocess.Popen("powershell -NoExit -Command \\\"& '{0}'\\\"".format(sys.argv[0]))
2020 return
2121 main()
2222
4343 f.writelines(lines)
4444
4545 # install dependencies and invoke PyInstaller
46 commands = ["pip install pipenv==2018.11.26",
47 "pipenv sync --dev",
46 commands = ["pip install pipenv==2021.5.29",
47 f"pipenv --python {sys.version_info.major}.{sys.version_info.minor} sync --dev",
4848 "pipenv run pyinstaller --log-level=DEBUG instaloader.spec"]
4949
5050 for command in commands:
+0
-7
docs/_static/bootstrap-4.1.3.bundle.min.js less more
0 /*!
1 * Bootstrap v4.1.3 (https://getbootstrap.com/)
2 * Copyright 2011-2018 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
3 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
4 */
5 !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("jquery")):"function"==typeof define&&define.amd?define(["exports","jquery"],t):t(e.bootstrap={},e.jQuery)}(this,function(e,t){"use strict";function i(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}function s(e,t,n){return t&&i(e.prototype,t),n&&i(e,n),e}function l(r){for(var e=1;e<arguments.length;e++){var o=null!=arguments[e]?arguments[e]:{},t=Object.keys(o);"function"==typeof Object.getOwnPropertySymbols&&(t=t.concat(Object.getOwnPropertySymbols(o).filter(function(e){return Object.getOwnPropertyDescriptor(o,e).enumerable}))),t.forEach(function(e){var t,n,i;t=r,i=o[n=e],n in t?Object.defineProperty(t,n,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[n]=i})}return r}for(var r,n,o,a,c,u,f,h,d,p,m,g,_,v,y,E,b,w,C,T,S,D,A,I,O,N,k,x,P,L,j,H,M,F,W,R,U,B,q,K,Q,Y,V,z,G,J,Z,X,$,ee,te,ne,ie,re,oe,se,ae,le,ce,ue,fe,he,de,pe,me,ge,_e,ve,ye,Ee,be,we=function(i){var t="transitionend";function e(e){var t=this,n=!1;return i(this).one(l.TRANSITION_END,function(){n=!0}),setTimeout(function(){n||l.triggerTransitionEnd(t)},e),this}var l={TRANSITION_END:"bsTransitionEnd",getUID:function(e){for(;e+=~~(1e6*Math.random()),document.getElementById(e););return e},getSelectorFromElement:function(e){var t=e.getAttribute("data-target");t&&"#"!==t||(t=e.getAttribute("href")||"");try{return document.querySelector(t)?t:null}catch(e){return null}},getTransitionDurationFromElement:function(e){if(!e)return 0;var t=i(e).css("transition-duration");return parseFloat(t)?(t=t.split(",")[0],1e3*parseFloat(t)):0},reflow:function(e){return e.offsetHeight},triggerTransitionEnd:function(e){i(e).trigger(t)},supportsTransitionEnd:function(){return Boolean(t)},isElement:function(e){return(e[0]||e).nodeType},typeCheckConfig:function(e,t,n){for(var i in n)if(Object.prototype.hasOwnProperty.call(n,i)){var r=n[i],o=t[i],s=o&&l.isElement(o)?"element":(a=o,{}.toString.call(a).match(/\s([a-z]+)/i)[1].toLowerCase());if(!new RegExp(r).test(s))throw new Error(e.toUpperCase()+': Option "'+i+'" provided type "'+s+'" but expected type "'+r+'".')}var a}};return i.fn.emulateTransitionEnd=e,i.event.special[l.TRANSITION_END]={bindType:t,delegateType:t,handle:function(e){if(i(e.target).is(this))return e.handleObj.handler.apply(this,arguments)}},l}(t=t&&t.hasOwnProperty("default")?t.default:t),Ce=(n="alert",a="."+(o="bs.alert"),c=(r=t).fn[n],u={CLOSE:"close"+a,CLOSED:"closed"+a,CLICK_DATA_API:"click"+a+".data-api"},f="alert",h="fade",d="show",p=function(){function i(e){this._element=e}var e=i.prototype;return e.close=function(e){var t=this._element;e&&(t=this._getRootElement(e)),this._triggerCloseEvent(t).isDefaultPrevented()||this._removeElement(t)},e.dispose=function(){r.removeData(this._element,o),this._element=null},e._getRootElement=function(e){var t=we.getSelectorFromElement(e),n=!1;return t&&(n=document.querySelector(t)),n||(n=r(e).closest("."+f)[0]),n},e._triggerCloseEvent=function(e){var t=r.Event(u.CLOSE);return r(e).trigger(t),t},e._removeElement=function(t){var n=this;if(r(t).removeClass(d),r(t).hasClass(h)){var e=we.getTransitionDurationFromElement(t);r(t).one(we.TRANSITION_END,function(e){return n._destroyElement(t,e)}).emulateTransitionEnd(e)}else this._destroyElement(t)},e._destroyElement=function(e){r(e).detach().trigger(u.CLOSED).remove()},i._jQueryInterface=function(n){return this.each(function(){var e=r(this),t=e.data(o);t||(t=new i(this),e.data(o,t)),"close"===n&&t[n](this)})},i._handleDismiss=function(t){return function(e){e&&e.preventDefault(),t.close(this)}},s(i,null,[{key:"VERSION",get:function(){return"4.1.3"}}]),i}(),r(document).on(u.CLICK_DATA_API,'[data-dismiss="alert"]',p._handleDismiss(new p)),r.fn[n]=p._jQueryInterface,r.fn[n].Constructor=p,r.fn[n].noConflict=function(){return r.fn[n]=c,p._jQueryInterface},p),Te=(g="button",v="."+(_="bs.button"),y=".data-api",E=(m=t).fn[g],b="active",w="btn",T='[data-toggle^="button"]',S='[data-toggle="buttons"]',D="input",A=".active",I=".btn",O={CLICK_DATA_API:"click"+v+y,FOCUS_BLUR_DATA_API:(C="focus")+v+y+" blur"+v+y},N=function(){function n(e){this._element=e}var e=n.prototype;return e.toggle=function(){var e=!0,t=!0,n=m(this._element).closest(S)[0];if(n){var i=this._element.querySelector(D);if(i){if("radio"===i.type)if(i.checked&&this._element.classList.contains(b))e=!1;else{var r=n.querySelector(A);r&&m(r).removeClass(b)}if(e){if(i.hasAttribute("disabled")||n.hasAttribute("disabled")||i.classList.contains("disabled")||n.classList.contains("disabled"))return;i.checked=!this._element.classList.contains(b),m(i).trigger("change")}i.focus(),t=!1}}t&&this._element.setAttribute("aria-pressed",!this._element.classList.contains(b)),e&&m(this._element).toggleClass(b)},e.dispose=function(){m.removeData(this._element,_),this._element=null},n._jQueryInterface=function(t){return this.each(function(){var e=m(this).data(_);e||(e=new n(this),m(this).data(_,e)),"toggle"===t&&e[t]()})},s(n,null,[{key:"VERSION",get:function(){return"4.1.3"}}]),n}(),m(document).on(O.CLICK_DATA_API,T,function(e){e.preventDefault();var t=e.target;m(t).hasClass(w)||(t=m(t).closest(I)),N._jQueryInterface.call(m(t),"toggle")}).on(O.FOCUS_BLUR_DATA_API,T,function(e){var t=m(e.target).closest(I)[0];m(t).toggleClass(C,/^focus(in)?$/.test(e.type))}),m.fn[g]=N._jQueryInterface,m.fn[g].Constructor=N,m.fn[g].noConflict=function(){return m.fn[g]=E,N._jQueryInterface},N),Se=(x="carousel",L="."+(P="bs.carousel"),j=".data-api",H=(k=t).fn[x],M={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0},F={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean"},W="next",R="prev",U="left",B="right",q={SLIDE:"slide"+L,SLID:"slid"+L,KEYDOWN:"keydown"+L,MOUSEENTER:"mouseenter"+L,MOUSELEAVE:"mouseleave"+L,TOUCHEND:"touchend"+L,LOAD_DATA_API:"load"+L+j,CLICK_DATA_API:"click"+L+j},K="carousel",Q="active",Y="slide",V="carousel-item-right",z="carousel-item-left",G="carousel-item-next",J="carousel-item-prev",Z=".active",X=".active.carousel-item",$=".carousel-item",ee=".carousel-item-next, .carousel-item-prev",te=".carousel-indicators",ne="[data-slide], [data-slide-to]",ie='[data-ride="carousel"]',re=function(){function o(e,t){this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this._config=this._getConfig(t),this._element=k(e)[0],this._indicatorsElement=this._element.querySelector(te),this._addEventListeners()}var e=o.prototype;return e.next=function(){this._isSliding||this._slide(W)},e.nextWhenVisible=function(){!document.hidden&&k(this._element).is(":visible")&&"hidden"!==k(this._element).css("visibility")&&this.next()},e.prev=function(){this._isSliding||this._slide(R)},e.pause=function(e){e||(this._isPaused=!0),this._element.querySelector(ee)&&(we.triggerTransitionEnd(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},e.cycle=function(e){e||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config.interval&&!this._isPaused&&(this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},e.to=function(e){var t=this;this._activeElement=this._element.querySelector(X);var n=this._getItemIndex(this._activeElement);if(!(e>this._items.length-1||e<0))if(this._isSliding)k(this._element).one(q.SLID,function(){return t.to(e)});else{if(n===e)return this.pause(),void this.cycle();var i=n<e?W:R;this._slide(i,this._items[e])}},e.dispose=function(){k(this._element).off(L),k.removeData(this._element,P),this._items=null,this._config=null,this._element=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},e._getConfig=function(e){return e=l({},M,e),we.typeCheckConfig(x,e,F),e},e._addEventListeners=function(){var t=this;this._config.keyboard&&k(this._element).on(q.KEYDOWN,function(e){return t._keydown(e)}),"hover"===this._config.pause&&(k(this._element).on(q.MOUSEENTER,function(e){return t.pause(e)}).on(q.MOUSELEAVE,function(e){return t.cycle(e)}),"ontouchstart"in document.documentElement&&k(this._element).on(q.TOUCHEND,function(){t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout(function(e){return t.cycle(e)},500+t._config.interval)}))},e._keydown=function(e){if(!/input|textarea/i.test(e.target.tagName))switch(e.which){case 37:e.preventDefault(),this.prev();break;case 39:e.preventDefault(),this.next()}},e._getItemIndex=function(e){return this._items=e&&e.parentNode?[].slice.call(e.parentNode.querySelectorAll($)):[],this._items.indexOf(e)},e._getItemByDirection=function(e,t){var n=e===W,i=e===R,r=this._getItemIndex(t),o=this._items.length-1;if((i&&0===r||n&&r===o)&&!this._config.wrap)return t;var s=(r+(e===R?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},e._triggerSlideEvent=function(e,t){var n=this._getItemIndex(e),i=this._getItemIndex(this._element.querySelector(X)),r=k.Event(q.SLIDE,{relatedTarget:e,direction:t,from:i,to:n});return k(this._element).trigger(r),r},e._setActiveIndicatorElement=function(e){if(this._indicatorsElement){var t=[].slice.call(this._indicatorsElement.querySelectorAll(Z));k(t).removeClass(Q);var n=this._indicatorsElement.children[this._getItemIndex(e)];n&&k(n).addClass(Q)}},e._slide=function(e,t){var n,i,r,o=this,s=this._element.querySelector(X),a=this._getItemIndex(s),l=t||s&&this._getItemByDirection(e,s),c=this._getItemIndex(l),u=Boolean(this._interval);if(e===W?(n=z,i=G,r=U):(n=V,i=J,r=B),l&&k(l).hasClass(Q))this._isSliding=!1;else if(!this._triggerSlideEvent(l,r).isDefaultPrevented()&&s&&l){this._isSliding=!0,u&&this.pause(),this._setActiveIndicatorElement(l);var f=k.Event(q.SLID,{relatedTarget:l,direction:r,from:a,to:c});if(k(this._element).hasClass(Y)){k(l).addClass(i),we.reflow(l),k(s).addClass(n),k(l).addClass(n);var h=we.getTransitionDurationFromElement(s);k(s).one(we.TRANSITION_END,function(){k(l).removeClass(n+" "+i).addClass(Q),k(s).removeClass(Q+" "+i+" "+n),o._isSliding=!1,setTimeout(function(){return k(o._element).trigger(f)},0)}).emulateTransitionEnd(h)}else k(s).removeClass(Q),k(l).addClass(Q),this._isSliding=!1,k(this._element).trigger(f);u&&this.cycle()}},o._jQueryInterface=function(i){return this.each(function(){var e=k(this).data(P),t=l({},M,k(this).data());"object"==typeof i&&(t=l({},t,i));var n="string"==typeof i?i:t.slide;if(e||(e=new o(this,t),k(this).data(P,e)),"number"==typeof i)e.to(i);else if("string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n]()}else t.interval&&(e.pause(),e.cycle())})},o._dataApiClickHandler=function(e){var t=we.getSelectorFromElement(this);if(t){var n=k(t)[0];if(n&&k(n).hasClass(K)){var i=l({},k(n).data(),k(this).data()),r=this.getAttribute("data-slide-to");r&&(i.interval=!1),o._jQueryInterface.call(k(n),i),r&&k(n).data(P).to(r),e.preventDefault()}}},s(o,null,[{key:"VERSION",get:function(){return"4.1.3"}},{key:"Default",get:function(){return M}}]),o}(),k(document).on(q.CLICK_DATA_API,ne,re._dataApiClickHandler),k(window).on(q.LOAD_DATA_API,function(){for(var e=[].slice.call(document.querySelectorAll(ie)),t=0,n=e.length;t<n;t++){var i=k(e[t]);re._jQueryInterface.call(i,i.data())}}),k.fn[x]=re._jQueryInterface,k.fn[x].Constructor=re,k.fn[x].noConflict=function(){return k.fn[x]=H,re._jQueryInterface},re),De=(se="collapse",le="."+(ae="bs.collapse"),ce=(oe=t).fn[se],ue={toggle:!0,parent:""},fe={toggle:"boolean",parent:"(string|element)"},he={SHOW:"show"+le,SHOWN:"shown"+le,HIDE:"hide"+le,HIDDEN:"hidden"+le,CLICK_DATA_API:"click"+le+".data-api"},de="show",pe="collapse",me="collapsing",ge="collapsed",_e="width",ve="height",ye=".show, .collapsing",Ee='[data-toggle="collapse"]',be=function(){function a(t,e){this._isTransitioning=!1,this._element=t,this._config=this._getConfig(e),this._triggerArray=oe.makeArray(document.querySelectorAll('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'));for(var n=[].slice.call(document.querySelectorAll(Ee)),i=0,r=n.length;i<r;i++){var o=n[i],s=we.getSelectorFromElement(o),a=[].slice.call(document.querySelectorAll(s)).filter(function(e){return e===t});null!==s&&0<a.length&&(this._selector=s,this._triggerArray.push(o))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var e=a.prototype;return e.toggle=function(){oe(this._element).hasClass(de)?this.hide():this.show()},e.show=function(){var e,t,n=this;if(!this._isTransitioning&&!oe(this._element).hasClass(de)&&(this._parent&&0===(e=[].slice.call(this._parent.querySelectorAll(ye)).filter(function(e){return e.getAttribute("data-parent")===n._config.parent})).length&&(e=null),!(e&&(t=oe(e).not(this._selector).data(ae))&&t._isTransitioning))){var i=oe.Event(he.SHOW);if(oe(this._element).trigger(i),!i.isDefaultPrevented()){e&&(a._jQueryInterface.call(oe(e).not(this._selector),"hide"),t||oe(e).data(ae,null));var r=this._getDimension();oe(this._element).removeClass(pe).addClass(me),this._element.style[r]=0,this._triggerArray.length&&oe(this._triggerArray).removeClass(ge).attr("aria-expanded",!0),this.setTransitioning(!0);var o="scroll"+(r[0].toUpperCase()+r.slice(1)),s=we.getTransitionDurationFromElement(this._element);oe(this._element).one(we.TRANSITION_END,function(){oe(n._element).removeClass(me).addClass(pe).addClass(de),n._element.style[r]="",n.setTransitioning(!1),oe(n._element).trigger(he.SHOWN)}).emulateTransitionEnd(s),this._element.style[r]=this._element[o]+"px"}}},e.hide=function(){var e=this;if(!this._isTransitioning&&oe(this._element).hasClass(de)){var t=oe.Event(he.HIDE);if(oe(this._element).trigger(t),!t.isDefaultPrevented()){var n=this._getDimension();this._element.style[n]=this._element.getBoundingClientRect()[n]+"px",we.reflow(this._element),oe(this._element).addClass(me).removeClass(pe).removeClass(de);var i=this._triggerArray.length;if(0<i)for(var r=0;r<i;r++){var o=this._triggerArray[r],s=we.getSelectorFromElement(o);if(null!==s)oe([].slice.call(document.querySelectorAll(s))).hasClass(de)||oe(o).addClass(ge).attr("aria-expanded",!1)}this.setTransitioning(!0);this._element.style[n]="";var a=we.getTransitionDurationFromElement(this._element);oe(this._element).one(we.TRANSITION_END,function(){e.setTransitioning(!1),oe(e._element).removeClass(me).addClass(pe).trigger(he.HIDDEN)}).emulateTransitionEnd(a)}}},e.setTransitioning=function(e){this._isTransitioning=e},e.dispose=function(){oe.removeData(this._element,ae),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},e._getConfig=function(e){return(e=l({},ue,e)).toggle=Boolean(e.toggle),we.typeCheckConfig(se,e,fe),e},e._getDimension=function(){return oe(this._element).hasClass(_e)?_e:ve},e._getParent=function(){var n=this,e=null;we.isElement(this._config.parent)?(e=this._config.parent,"undefined"!=typeof this._config.parent.jquery&&(e=this._config.parent[0])):e=document.querySelector(this._config.parent);var t='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',i=[].slice.call(e.querySelectorAll(t));return oe(i).each(function(e,t){n._addAriaAndCollapsedClass(a._getTargetFromElement(t),[t])}),e},e._addAriaAndCollapsedClass=function(e,t){if(e){var n=oe(e).hasClass(de);t.length&&oe(t).toggleClass(ge,!n).attr("aria-expanded",n)}},a._getTargetFromElement=function(e){var t=we.getSelectorFromElement(e);return t?document.querySelector(t):null},a._jQueryInterface=function(i){return this.each(function(){var e=oe(this),t=e.data(ae),n=l({},ue,e.data(),"object"==typeof i&&i?i:{});if(!t&&n.toggle&&/show|hide/.test(i)&&(n.toggle=!1),t||(t=new a(this,n),e.data(ae,t)),"string"==typeof i){if("undefined"==typeof t[i])throw new TypeError('No method named "'+i+'"');t[i]()}})},s(a,null,[{key:"VERSION",get:function(){return"4.1.3"}},{key:"Default",get:function(){return ue}}]),a}(),oe(document).on(he.CLICK_DATA_API,Ee,function(e){"A"===e.currentTarget.tagName&&e.preventDefault();var n=oe(this),t=we.getSelectorFromElement(this),i=[].slice.call(document.querySelectorAll(t));oe(i).each(function(){var e=oe(this),t=e.data(ae)?"toggle":n.data();be._jQueryInterface.call(e,t)})}),oe.fn[se]=be._jQueryInterface,oe.fn[se].Constructor=be,oe.fn[se].noConflict=function(){return oe.fn[se]=ce,be._jQueryInterface},be),Ae="undefined"!=typeof window&&"undefined"!=typeof document,Ie=["Edge","Trident","Firefox"],Oe=0,Ne=0;Ne<Ie.length;Ne+=1)if(Ae&&0<=navigator.userAgent.indexOf(Ie[Ne])){Oe=1;break}var ke=Ae&&window.Promise?function(e){var t=!1;return function(){t||(t=!0,window.Promise.resolve().then(function(){t=!1,e()}))}}:function(e){var t=!1;return function(){t||(t=!0,setTimeout(function(){t=!1,e()},Oe))}};function xe(e){return e&&"[object Function]"==={}.toString.call(e)}function Pe(e,t){if(1!==e.nodeType)return[];var n=getComputedStyle(e,null);return t?n[t]:n}function Le(e){return"HTML"===e.nodeName?e:e.parentNode||e.host}function je(e){if(!e)return document.body;switch(e.nodeName){case"HTML":case"BODY":return e.ownerDocument.body;case"#document":return e.body}var t=Pe(e),n=t.overflow,i=t.overflowX,r=t.overflowY;return/(auto|scroll|overlay)/.test(n+r+i)?e:je(Le(e))}var He=Ae&&!(!window.MSInputMethodContext||!document.documentMode),Me=Ae&&/MSIE 10/.test(navigator.userAgent);function Fe(e){return 11===e?He:10===e?Me:He||Me}function We(e){if(!e)return document.documentElement;for(var t=Fe(10)?document.body:null,n=e.offsetParent;n===t&&e.nextElementSibling;)n=(e=e.nextElementSibling).offsetParent;var i=n&&n.nodeName;return i&&"BODY"!==i&&"HTML"!==i?-1!==["TD","TABLE"].indexOf(n.nodeName)&&"static"===Pe(n,"position")?We(n):n:e?e.ownerDocument.documentElement:document.documentElement}function Re(e){return null!==e.parentNode?Re(e.parentNode):e}function Ue(e,t){if(!(e&&e.nodeType&&t&&t.nodeType))return document.documentElement;var n=e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING,i=n?e:t,r=n?t:e,o=document.createRange();o.setStart(i,0),o.setEnd(r,0);var s,a,l=o.commonAncestorContainer;if(e!==l&&t!==l||i.contains(r))return"BODY"===(a=(s=l).nodeName)||"HTML"!==a&&We(s.firstElementChild)!==s?We(l):l;var c=Re(e);return c.host?Ue(c.host,t):Ue(e,Re(t).host)}function Be(e){var t="top"===(1<arguments.length&&void 0!==arguments[1]?arguments[1]:"top")?"scrollTop":"scrollLeft",n=e.nodeName;if("BODY"===n||"HTML"===n){var i=e.ownerDocument.documentElement;return(e.ownerDocument.scrollingElement||i)[t]}return e[t]}function qe(e,t){var n="x"===t?"Left":"Top",i="Left"===n?"Right":"Bottom";return parseFloat(e["border"+n+"Width"],10)+parseFloat(e["border"+i+"Width"],10)}function Ke(e,t,n,i){return Math.max(t["offset"+e],t["scroll"+e],n["client"+e],n["offset"+e],n["scroll"+e],Fe(10)?n["offset"+e]+i["margin"+("Height"===e?"Top":"Left")]+i["margin"+("Height"===e?"Bottom":"Right")]:0)}function Qe(){var e=document.body,t=document.documentElement,n=Fe(10)&&getComputedStyle(t);return{height:Ke("Height",e,t,n),width:Ke("Width",e,t,n)}}var Ye=function(){function i(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(e,t,n){return t&&i(e.prototype,t),n&&i(e,n),e}}(),Ve=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e},ze=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&(e[i]=n[i])}return e};function Ge(e){return ze({},e,{right:e.left+e.width,bottom:e.top+e.height})}function Je(e){var t={};try{if(Fe(10)){t=e.getBoundingClientRect();var n=Be(e,"top"),i=Be(e,"left");t.top+=n,t.left+=i,t.bottom+=n,t.right+=i}else t=e.getBoundingClientRect()}catch(e){}var r={left:t.left,top:t.top,width:t.right-t.left,height:t.bottom-t.top},o="HTML"===e.nodeName?Qe():{},s=o.width||e.clientWidth||r.right-r.left,a=o.height||e.clientHeight||r.bottom-r.top,l=e.offsetWidth-s,c=e.offsetHeight-a;if(l||c){var u=Pe(e);l-=qe(u,"x"),c-=qe(u,"y"),r.width-=l,r.height-=c}return Ge(r)}function Ze(e,t){var n=2<arguments.length&&void 0!==arguments[2]&&arguments[2],i=Fe(10),r="HTML"===t.nodeName,o=Je(e),s=Je(t),a=je(e),l=Pe(t),c=parseFloat(l.borderTopWidth,10),u=parseFloat(l.borderLeftWidth,10);n&&"HTML"===t.nodeName&&(s.top=Math.max(s.top,0),s.left=Math.max(s.left,0));var f=Ge({top:o.top-s.top-c,left:o.left-s.left-u,width:o.width,height:o.height});if(f.marginTop=0,f.marginLeft=0,!i&&r){var h=parseFloat(l.marginTop,10),d=parseFloat(l.marginLeft,10);f.top-=c-h,f.bottom-=c-h,f.left-=u-d,f.right-=u-d,f.marginTop=h,f.marginLeft=d}return(i&&!n?t.contains(a):t===a&&"BODY"!==a.nodeName)&&(f=function(e,t){var n=2<arguments.length&&void 0!==arguments[2]&&arguments[2],i=Be(t,"top"),r=Be(t,"left"),o=n?-1:1;return e.top+=i*o,e.bottom+=i*o,e.left+=r*o,e.right+=r*o,e}(f,t)),f}function Xe(e){if(!e||!e.parentElement||Fe())return document.documentElement;for(var t=e.parentElement;t&&"none"===Pe(t,"transform");)t=t.parentElement;return t||document.documentElement}function $e(e,t,n,i){var r=4<arguments.length&&void 0!==arguments[4]&&arguments[4],o={top:0,left:0},s=r?Xe(e):Ue(e,t);if("viewport"===i)o=function(e){var t=1<arguments.length&&void 0!==arguments[1]&&arguments[1],n=e.ownerDocument.documentElement,i=Ze(e,n),r=Math.max(n.clientWidth,window.innerWidth||0),o=Math.max(n.clientHeight,window.innerHeight||0),s=t?0:Be(n),a=t?0:Be(n,"left");return Ge({top:s-i.top+i.marginTop,left:a-i.left+i.marginLeft,width:r,height:o})}(s,r);else{var a=void 0;"scrollParent"===i?"BODY"===(a=je(Le(t))).nodeName&&(a=e.ownerDocument.documentElement):a="window"===i?e.ownerDocument.documentElement:i;var l=Ze(a,s,r);if("HTML"!==a.nodeName||function e(t){var n=t.nodeName;return"BODY"!==n&&"HTML"!==n&&("fixed"===Pe(t,"position")||e(Le(t)))}(s))o=l;else{var c=Qe(),u=c.height,f=c.width;o.top+=l.top-l.marginTop,o.bottom=u+l.top,o.left+=l.left-l.marginLeft,o.right=f+l.left}}return o.left+=n,o.top+=n,o.right-=n,o.bottom-=n,o}function et(e,t,i,n,r){var o=5<arguments.length&&void 0!==arguments[5]?arguments[5]:0;if(-1===e.indexOf("auto"))return e;var s=$e(i,n,o,r),a={top:{width:s.width,height:t.top-s.top},right:{width:s.right-t.right,height:s.height},bottom:{width:s.width,height:s.bottom-t.bottom},left:{width:t.left-s.left,height:s.height}},l=Object.keys(a).map(function(e){return ze({key:e},a[e],{area:(t=a[e],t.width*t.height)});var t}).sort(function(e,t){return t.area-e.area}),c=l.filter(function(e){var t=e.width,n=e.height;return t>=i.clientWidth&&n>=i.clientHeight}),u=0<c.length?c[0].key:l[0].key,f=e.split("-")[1];return u+(f?"-"+f:"")}function tt(e,t,n){var i=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return Ze(n,i?Xe(t):Ue(t,n),i)}function nt(e){var t=getComputedStyle(e),n=parseFloat(t.marginTop)+parseFloat(t.marginBottom),i=parseFloat(t.marginLeft)+parseFloat(t.marginRight);return{width:e.offsetWidth+i,height:e.offsetHeight+n}}function it(e){var t={left:"right",right:"left",bottom:"top",top:"bottom"};return e.replace(/left|right|bottom|top/g,function(e){return t[e]})}function rt(e,t,n){n=n.split("-")[0];var i=nt(e),r={width:i.width,height:i.height},o=-1!==["right","left"].indexOf(n),s=o?"top":"left",a=o?"left":"top",l=o?"height":"width",c=o?"width":"height";return r[s]=t[s]+t[l]/2-i[l]/2,r[a]=n===a?t[a]-i[c]:t[it(a)],r}function ot(e,t){return Array.prototype.find?e.find(t):e.filter(t)[0]}function st(e,n,t){return(void 0===t?e:e.slice(0,function(e,t,n){if(Array.prototype.findIndex)return e.findIndex(function(e){return e[t]===n});var i=ot(e,function(e){return e[t]===n});return e.indexOf(i)}(e,"name",t))).forEach(function(e){e.function&&console.warn("`modifier.function` is deprecated, use `modifier.fn`!");var t=e.function||e.fn;e.enabled&&xe(t)&&(n.offsets.popper=Ge(n.offsets.popper),n.offsets.reference=Ge(n.offsets.reference),n=t(n,e))}),n}function at(e,n){return e.some(function(e){var t=e.name;return e.enabled&&t===n})}function lt(e){for(var t=[!1,"ms","Webkit","Moz","O"],n=e.charAt(0).toUpperCase()+e.slice(1),i=0;i<t.length;i++){var r=t[i],o=r?""+r+n:e;if("undefined"!=typeof document.body.style[o])return o}return null}function ct(e){var t=e.ownerDocument;return t?t.defaultView:window}function ut(e,t,n,i){n.updateBound=i,ct(e).addEventListener("resize",n.updateBound,{passive:!0});var r=je(e);return function e(t,n,i,r){var o="BODY"===t.nodeName,s=o?t.ownerDocument.defaultView:t;s.addEventListener(n,i,{passive:!0}),o||e(je(s.parentNode),n,i,r),r.push(s)}(r,"scroll",n.updateBound,n.scrollParents),n.scrollElement=r,n.eventsEnabled=!0,n}function ft(){var e,t;this.state.eventsEnabled&&(cancelAnimationFrame(this.scheduleUpdate),this.state=(e=this.reference,t=this.state,ct(e).removeEventListener("resize",t.updateBound),t.scrollParents.forEach(function(e){e.removeEventListener("scroll",t.updateBound)}),t.updateBound=null,t.scrollParents=[],t.scrollElement=null,t.eventsEnabled=!1,t))}function ht(e){return""!==e&&!isNaN(parseFloat(e))&&isFinite(e)}function dt(n,i){Object.keys(i).forEach(function(e){var t="";-1!==["width","height","top","right","bottom","left"].indexOf(e)&&ht(i[e])&&(t="px"),n.style[e]=i[e]+t})}function pt(e,t,n){var i=ot(e,function(e){return e.name===t}),r=!!i&&e.some(function(e){return e.name===n&&e.enabled&&e.order<i.order});if(!r){var o="`"+t+"`",s="`"+n+"`";console.warn(s+" modifier is required by "+o+" modifier in order to work, be sure to include it before "+o+"!")}return r}var mt=["auto-start","auto","auto-end","top-start","top","top-end","right-start","right","right-end","bottom-end","bottom","bottom-start","left-end","left","left-start"],gt=mt.slice(3);function _t(e){var t=1<arguments.length&&void 0!==arguments[1]&&arguments[1],n=gt.indexOf(e),i=gt.slice(n+1).concat(gt.slice(0,n));return t?i.reverse():i}var vt="flip",yt="clockwise",Et="counterclockwise";function bt(e,r,o,t){var s=[0,0],a=-1!==["right","left"].indexOf(t),n=e.split(/(\+|\-)/).map(function(e){return e.trim()}),i=n.indexOf(ot(n,function(e){return-1!==e.search(/,|\s/)}));n[i]&&-1===n[i].indexOf(",")&&console.warn("Offsets separated by white space(s) are deprecated, use a comma (,) instead.");var l=/\s*,\s*|\s+/,c=-1!==i?[n.slice(0,i).concat([n[i].split(l)[0]]),[n[i].split(l)[1]].concat(n.slice(i+1))]:[n];return(c=c.map(function(e,t){var n=(1===t?!a:a)?"height":"width",i=!1;return e.reduce(function(e,t){return""===e[e.length-1]&&-1!==["+","-"].indexOf(t)?(e[e.length-1]=t,i=!0,e):i?(e[e.length-1]+=t,i=!1,e):e.concat(t)},[]).map(function(e){return function(e,t,n,i){var r=e.match(/((?:\-|\+)?\d*\.?\d*)(.*)/),o=+r[1],s=r[2];if(!o)return e;if(0===s.indexOf("%")){var a=void 0;switch(s){case"%p":a=n;break;case"%":case"%r":default:a=i}return Ge(a)[t]/100*o}if("vh"===s||"vw"===s)return("vh"===s?Math.max(document.documentElement.clientHeight,window.innerHeight||0):Math.max(document.documentElement.clientWidth,window.innerWidth||0))/100*o;return o}(e,n,r,o)})})).forEach(function(n,i){n.forEach(function(e,t){ht(e)&&(s[i]+=e*("-"===n[t-1]?-1:1))})}),s}var wt={placement:"bottom",positionFixed:!1,eventsEnabled:!0,removeOnDestroy:!1,onCreate:function(){},onUpdate:function(){},modifiers:{shift:{order:100,enabled:!0,fn:function(e){var t=e.placement,n=t.split("-")[0],i=t.split("-")[1];if(i){var r=e.offsets,o=r.reference,s=r.popper,a=-1!==["bottom","top"].indexOf(n),l=a?"left":"top",c=a?"width":"height",u={start:Ve({},l,o[l]),end:Ve({},l,o[l]+o[c]-s[c])};e.offsets.popper=ze({},s,u[i])}return e}},offset:{order:200,enabled:!0,fn:function(e,t){var n=t.offset,i=e.placement,r=e.offsets,o=r.popper,s=r.reference,a=i.split("-")[0],l=void 0;return l=ht(+n)?[+n,0]:bt(n,o,s,a),"left"===a?(o.top+=l[0],o.left-=l[1]):"right"===a?(o.top+=l[0],o.left+=l[1]):"top"===a?(o.left+=l[0],o.top-=l[1]):"bottom"===a&&(o.left+=l[0],o.top+=l[1]),e.popper=o,e},offset:0},preventOverflow:{order:300,enabled:!0,fn:function(e,i){var t=i.boundariesElement||We(e.instance.popper);e.instance.reference===t&&(t=We(t));var n=lt("transform"),r=e.instance.popper.style,o=r.top,s=r.left,a=r[n];r.top="",r.left="",r[n]="";var l=$e(e.instance.popper,e.instance.reference,i.padding,t,e.positionFixed);r.top=o,r.left=s,r[n]=a,i.boundaries=l;var c=i.priority,u=e.offsets.popper,f={primary:function(e){var t=u[e];return u[e]<l[e]&&!i.escapeWithReference&&(t=Math.max(u[e],l[e])),Ve({},e,t)},secondary:function(e){var t="right"===e?"left":"top",n=u[t];return u[e]>l[e]&&!i.escapeWithReference&&(n=Math.min(u[t],l[e]-("right"===e?u.width:u.height))),Ve({},t,n)}};return c.forEach(function(e){var t=-1!==["left","top"].indexOf(e)?"primary":"secondary";u=ze({},u,f[t](e))}),e.offsets.popper=u,e},priority:["left","right","top","bottom"],padding:5,boundariesElement:"scrollParent"},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,n=t.popper,i=t.reference,r=e.placement.split("-")[0],o=Math.floor,s=-1!==["top","bottom"].indexOf(r),a=s?"right":"bottom",l=s?"left":"top",c=s?"width":"height";return n[a]<o(i[l])&&(e.offsets.popper[l]=o(i[l])-n[c]),n[l]>o(i[a])&&(e.offsets.popper[l]=o(i[a])),e}},arrow:{order:500,enabled:!0,fn:function(e,t){var n;if(!pt(e.instance.modifiers,"arrow","keepTogether"))return e;var i=t.element;if("string"==typeof i){if(!(i=e.instance.popper.querySelector(i)))return e}else if(!e.instance.popper.contains(i))return console.warn("WARNING: `arrow.element` must be child of its popper element!"),e;var r=e.placement.split("-")[0],o=e.offsets,s=o.popper,a=o.reference,l=-1!==["left","right"].indexOf(r),c=l?"height":"width",u=l?"Top":"Left",f=u.toLowerCase(),h=l?"left":"top",d=l?"bottom":"right",p=nt(i)[c];a[d]-p<s[f]&&(e.offsets.popper[f]-=s[f]-(a[d]-p)),a[f]+p>s[d]&&(e.offsets.popper[f]+=a[f]+p-s[d]),e.offsets.popper=Ge(e.offsets.popper);var m=a[f]+a[c]/2-p/2,g=Pe(e.instance.popper),_=parseFloat(g["margin"+u],10),v=parseFloat(g["border"+u+"Width"],10),y=m-e.offsets.popper[f]-_-v;return y=Math.max(Math.min(s[c]-p,y),0),e.arrowElement=i,e.offsets.arrow=(Ve(n={},f,Math.round(y)),Ve(n,h,""),n),e},element:"[x-arrow]"},flip:{order:600,enabled:!0,fn:function(p,m){if(at(p.instance.modifiers,"inner"))return p;if(p.flipped&&p.placement===p.originalPlacement)return p;var g=$e(p.instance.popper,p.instance.reference,m.padding,m.boundariesElement,p.positionFixed),_=p.placement.split("-")[0],v=it(_),y=p.placement.split("-")[1]||"",E=[];switch(m.behavior){case vt:E=[_,v];break;case yt:E=_t(_);break;case Et:E=_t(_,!0);break;default:E=m.behavior}return E.forEach(function(e,t){if(_!==e||E.length===t+1)return p;_=p.placement.split("-")[0],v=it(_);var n,i=p.offsets.popper,r=p.offsets.reference,o=Math.floor,s="left"===_&&o(i.right)>o(r.left)||"right"===_&&o(i.left)<o(r.right)||"top"===_&&o(i.bottom)>o(r.top)||"bottom"===_&&o(i.top)<o(r.bottom),a=o(i.left)<o(g.left),l=o(i.right)>o(g.right),c=o(i.top)<o(g.top),u=o(i.bottom)>o(g.bottom),f="left"===_&&a||"right"===_&&l||"top"===_&&c||"bottom"===_&&u,h=-1!==["top","bottom"].indexOf(_),d=!!m.flipVariations&&(h&&"start"===y&&a||h&&"end"===y&&l||!h&&"start"===y&&c||!h&&"end"===y&&u);(s||f||d)&&(p.flipped=!0,(s||f)&&(_=E[t+1]),d&&(y="end"===(n=y)?"start":"start"===n?"end":n),p.placement=_+(y?"-"+y:""),p.offsets.popper=ze({},p.offsets.popper,rt(p.instance.popper,p.offsets.reference,p.placement)),p=st(p.instance.modifiers,p,"flip"))}),p},behavior:"flip",padding:5,boundariesElement:"viewport"},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,n=t.split("-")[0],i=e.offsets,r=i.popper,o=i.reference,s=-1!==["left","right"].indexOf(n),a=-1===["top","left"].indexOf(n);return r[s?"left":"top"]=o[n]-(a?r[s?"width":"height"]:0),e.placement=it(t),e.offsets.popper=Ge(r),e}},hide:{order:800,enabled:!0,fn:function(e){if(!pt(e.instance.modifiers,"hide","preventOverflow"))return e;var t=e.offsets.reference,n=ot(e.instance.modifiers,function(e){return"preventOverflow"===e.name}).boundaries;if(t.bottom<n.top||t.left>n.right||t.top>n.bottom||t.right<n.left){if(!0===e.hide)return e;e.hide=!0,e.attributes["x-out-of-boundaries"]=""}else{if(!1===e.hide)return e;e.hide=!1,e.attributes["x-out-of-boundaries"]=!1}return e}},computeStyle:{order:850,enabled:!0,fn:function(e,t){var n=t.x,i=t.y,r=e.offsets.popper,o=ot(e.instance.modifiers,function(e){return"applyStyle"===e.name}).gpuAcceleration;void 0!==o&&console.warn("WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!");var s=void 0!==o?o:t.gpuAcceleration,a=Je(We(e.instance.popper)),l={position:r.position},c={left:Math.floor(r.left),top:Math.round(r.top),bottom:Math.round(r.bottom),right:Math.floor(r.right)},u="bottom"===n?"top":"bottom",f="right"===i?"left":"right",h=lt("transform"),d=void 0,p=void 0;if(p="bottom"===u?-a.height+c.bottom:c.top,d="right"===f?-a.width+c.right:c.left,s&&h)l[h]="translate3d("+d+"px, "+p+"px, 0)",l[u]=0,l[f]=0,l.willChange="transform";else{var m="bottom"===u?-1:1,g="right"===f?-1:1;l[u]=p*m,l[f]=d*g,l.willChange=u+", "+f}var _={"x-placement":e.placement};return e.attributes=ze({},_,e.attributes),e.styles=ze({},l,e.styles),e.arrowStyles=ze({},e.offsets.arrow,e.arrowStyles),e},gpuAcceleration:!0,x:"bottom",y:"right"},applyStyle:{order:900,enabled:!0,fn:function(e){var t,n;return dt(e.instance.popper,e.styles),t=e.instance.popper,n=e.attributes,Object.keys(n).forEach(function(e){!1!==n[e]?t.setAttribute(e,n[e]):t.removeAttribute(e)}),e.arrowElement&&Object.keys(e.arrowStyles).length&&dt(e.arrowElement,e.arrowStyles),e},onLoad:function(e,t,n,i,r){var o=tt(r,t,e,n.positionFixed),s=et(n.placement,o,t,e,n.modifiers.flip.boundariesElement,n.modifiers.flip.padding);return t.setAttribute("x-placement",s),dt(t,{position:n.positionFixed?"fixed":"absolute"}),n},gpuAcceleration:void 0}}},Ct=function(){function o(e,t){var n=this,i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{};!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,o),this.scheduleUpdate=function(){return requestAnimationFrame(n.update)},this.update=ke(this.update.bind(this)),this.options=ze({},o.Defaults,i),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=e&&e.jquery?e[0]:e,this.popper=t&&t.jquery?t[0]:t,this.options.modifiers={},Object.keys(ze({},o.Defaults.modifiers,i.modifiers)).forEach(function(e){n.options.modifiers[e]=ze({},o.Defaults.modifiers[e]||{},i.modifiers?i.modifiers[e]:{})}),this.modifiers=Object.keys(this.options.modifiers).map(function(e){return ze({name:e},n.options.modifiers[e])}).sort(function(e,t){return e.order-t.order}),this.modifiers.forEach(function(e){e.enabled&&xe(e.onLoad)&&e.onLoad(n.reference,n.popper,n.options,e,n.state)}),this.update();var r=this.options.eventsEnabled;r&&this.enableEventListeners(),this.state.eventsEnabled=r}return Ye(o,[{key:"update",value:function(){return function(){if(!this.state.isDestroyed){var e={instance:this,styles:{},arrowStyles:{},attributes:{},flipped:!1,offsets:{}};e.offsets.reference=tt(this.state,this.popper,this.reference,this.options.positionFixed),e.placement=et(this.options.placement,e.offsets.reference,this.popper,this.reference,this.options.modifiers.flip.boundariesElement,this.options.modifiers.flip.padding),e.originalPlacement=e.placement,e.positionFixed=this.options.positionFixed,e.offsets.popper=rt(this.popper,e.offsets.reference,e.placement),e.offsets.popper.position=this.options.positionFixed?"fixed":"absolute",e=st(this.modifiers,e),this.state.isCreated?this.options.onUpdate(e):(this.state.isCreated=!0,this.options.onCreate(e))}}.call(this)}},{key:"destroy",value:function(){return function(){return this.state.isDestroyed=!0,at(this.modifiers,"applyStyle")&&(this.popper.removeAttribute("x-placement"),this.popper.style.position="",this.popper.style.top="",this.popper.style.left="",this.popper.style.right="",this.popper.style.bottom="",this.popper.style.willChange="",this.popper.style[lt("transform")]=""),this.disableEventListeners(),this.options.removeOnDestroy&&this.popper.parentNode.removeChild(this.popper),this}.call(this)}},{key:"enableEventListeners",value:function(){return function(){this.state.eventsEnabled||(this.state=ut(this.reference,this.options,this.state,this.scheduleUpdate))}.call(this)}},{key:"disableEventListeners",value:function(){return ft.call(this)}}]),o}();Ct.Utils=("undefined"!=typeof window?window:global).PopperUtils,Ct.placements=mt,Ct.Defaults=wt;var Tt,St,Dt,At,It,Ot,Nt,kt,xt,Pt,Lt,jt,Ht,Mt,Ft,Wt,Rt,Ut,Bt,qt,Kt,Qt,Yt,Vt,zt,Gt,Jt,Zt,Xt,$t,en,tn,nn,rn,on,sn,an,ln,cn,un,fn,hn,dn,pn,mn,gn,_n,vn,yn,En,bn,wn,Cn,Tn,Sn,Dn,An,In,On,Nn,kn,xn,Pn,Ln,jn,Hn,Mn,Fn,Wn,Rn,Un,Bn,qn,Kn,Qn,Yn,Vn,zn,Gn,Jn,Zn,Xn,$n,ei,ti,ni,ii,ri,oi,si,ai,li,ci,ui,fi,hi,di,pi,mi,gi,_i,vi,yi,Ei,bi,wi,Ci,Ti,Si,Di,Ai,Ii,Oi,Ni,ki,xi,Pi,Li,ji,Hi,Mi,Fi,Wi,Ri,Ui,Bi=(St="dropdown",At="."+(Dt="bs.dropdown"),It=".data-api",Ot=(Tt=t).fn[St],Nt=new RegExp("38|40|27"),kt={HIDE:"hide"+At,HIDDEN:"hidden"+At,SHOW:"show"+At,SHOWN:"shown"+At,CLICK:"click"+At,CLICK_DATA_API:"click"+At+It,KEYDOWN_DATA_API:"keydown"+At+It,KEYUP_DATA_API:"keyup"+At+It},xt="disabled",Pt="show",Lt="dropup",jt="dropright",Ht="dropleft",Mt="dropdown-menu-right",Ft="position-static",Wt='[data-toggle="dropdown"]',Rt=".dropdown form",Ut=".dropdown-menu",Bt=".navbar-nav",qt=".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",Kt="top-start",Qt="top-end",Yt="bottom-start",Vt="bottom-end",zt="right-start",Gt="left-start",Jt={offset:0,flip:!0,boundary:"scrollParent",reference:"toggle",display:"dynamic"},Zt={offset:"(number|string|function)",flip:"boolean",boundary:"(string|element)",reference:"(string|element)",display:"string"},Xt=function(){function c(e,t){this._element=e,this._popper=null,this._config=this._getConfig(t),this._menu=this._getMenuElement(),this._inNavbar=this._detectNavbar(),this._addEventListeners()}var e=c.prototype;return e.toggle=function(){if(!this._element.disabled&&!Tt(this._element).hasClass(xt)){var e=c._getParentFromElement(this._element),t=Tt(this._menu).hasClass(Pt);if(c._clearMenus(),!t){var n={relatedTarget:this._element},i=Tt.Event(kt.SHOW,n);if(Tt(e).trigger(i),!i.isDefaultPrevented()){if(!this._inNavbar){if("undefined"==typeof Ct)throw new TypeError("Bootstrap dropdown require Popper.js (https://popper.js.org)");var r=this._element;"parent"===this._config.reference?r=e:we.isElement(this._config.reference)&&(r=this._config.reference,"undefined"!=typeof this._config.reference.jquery&&(r=this._config.reference[0])),"scrollParent"!==this._config.boundary&&Tt(e).addClass(Ft),this._popper=new Ct(r,this._menu,this._getPopperConfig())}"ontouchstart"in document.documentElement&&0===Tt(e).closest(Bt).length&&Tt(document.body).children().on("mouseover",null,Tt.noop),this._element.focus(),this._element.setAttribute("aria-expanded",!0),Tt(this._menu).toggleClass(Pt),Tt(e).toggleClass(Pt).trigger(Tt.Event(kt.SHOWN,n))}}}},e.dispose=function(){Tt.removeData(this._element,Dt),Tt(this._element).off(At),this._element=null,(this._menu=null)!==this._popper&&(this._popper.destroy(),this._popper=null)},e.update=function(){this._inNavbar=this._detectNavbar(),null!==this._popper&&this._popper.scheduleUpdate()},e._addEventListeners=function(){var t=this;Tt(this._element).on(kt.CLICK,function(e){e.preventDefault(),e.stopPropagation(),t.toggle()})},e._getConfig=function(e){return e=l({},this.constructor.Default,Tt(this._element).data(),e),we.typeCheckConfig(St,e,this.constructor.DefaultType),e},e._getMenuElement=function(){if(!this._menu){var e=c._getParentFromElement(this._element);e&&(this._menu=e.querySelector(Ut))}return this._menu},e._getPlacement=function(){var e=Tt(this._element.parentNode),t=Yt;return e.hasClass(Lt)?(t=Kt,Tt(this._menu).hasClass(Mt)&&(t=Qt)):e.hasClass(jt)?t=zt:e.hasClass(Ht)?t=Gt:Tt(this._menu).hasClass(Mt)&&(t=Vt),t},e._detectNavbar=function(){return 0<Tt(this._element).closest(".navbar").length},e._getPopperConfig=function(){var t=this,e={};"function"==typeof this._config.offset?e.fn=function(e){return e.offsets=l({},e.offsets,t._config.offset(e.offsets)||{}),e}:e.offset=this._config.offset;var n={placement:this._getPlacement(),modifiers:{offset:e,flip:{enabled:this._config.flip},preventOverflow:{boundariesElement:this._config.boundary}}};return"static"===this._config.display&&(n.modifiers.applyStyle={enabled:!1}),n},c._jQueryInterface=function(t){return this.each(function(){var e=Tt(this).data(Dt);if(e||(e=new c(this,"object"==typeof t?t:null),Tt(this).data(Dt,e)),"string"==typeof t){if("undefined"==typeof e[t])throw new TypeError('No method named "'+t+'"');e[t]()}})},c._clearMenus=function(e){if(!e||3!==e.which&&("keyup"!==e.type||9===e.which))for(var t=[].slice.call(document.querySelectorAll(Wt)),n=0,i=t.length;n<i;n++){var r=c._getParentFromElement(t[n]),o=Tt(t[n]).data(Dt),s={relatedTarget:t[n]};if(e&&"click"===e.type&&(s.clickEvent=e),o){var a=o._menu;if(Tt(r).hasClass(Pt)&&!(e&&("click"===e.type&&/input|textarea/i.test(e.target.tagName)||"keyup"===e.type&&9===e.which)&&Tt.contains(r,e.target))){var l=Tt.Event(kt.HIDE,s);Tt(r).trigger(l),l.isDefaultPrevented()||("ontouchstart"in document.documentElement&&Tt(document.body).children().off("mouseover",null,Tt.noop),t[n].setAttribute("aria-expanded","false"),Tt(a).removeClass(Pt),Tt(r).removeClass(Pt).trigger(Tt.Event(kt.HIDDEN,s)))}}}},c._getParentFromElement=function(e){var t,n=we.getSelectorFromElement(e);return n&&(t=document.querySelector(n)),t||e.parentNode},c._dataApiKeydownHandler=function(e){if((/input|textarea/i.test(e.target.tagName)?!(32===e.which||27!==e.which&&(40!==e.which&&38!==e.which||Tt(e.target).closest(Ut).length)):Nt.test(e.which))&&(e.preventDefault(),e.stopPropagation(),!this.disabled&&!Tt(this).hasClass(xt))){var t=c._getParentFromElement(this),n=Tt(t).hasClass(Pt);if((n||27===e.which&&32===e.which)&&(!n||27!==e.which&&32!==e.which)){var i=[].slice.call(t.querySelectorAll(qt));if(0!==i.length){var r=i.indexOf(e.target);38===e.which&&0<r&&r--,40===e.which&&r<i.length-1&&r++,r<0&&(r=0),i[r].focus()}}else{if(27===e.which){var o=t.querySelector(Wt);Tt(o).trigger("focus")}Tt(this).trigger("click")}}},s(c,null,[{key:"VERSION",get:function(){return"4.1.3"}},{key:"Default",get:function(){return Jt}},{key:"DefaultType",get:function(){return Zt}}]),c}(),Tt(document).on(kt.KEYDOWN_DATA_API,Wt,Xt._dataApiKeydownHandler).on(kt.KEYDOWN_DATA_API,Ut,Xt._dataApiKeydownHandler).on(kt.CLICK_DATA_API+" "+kt.KEYUP_DATA_API,Xt._clearMenus).on(kt.CLICK_DATA_API,Wt,function(e){e.preventDefault(),e.stopPropagation(),Xt._jQueryInterface.call(Tt(this),"toggle")}).on(kt.CLICK_DATA_API,Rt,function(e){e.stopPropagation()}),Tt.fn[St]=Xt._jQueryInterface,Tt.fn[St].Constructor=Xt,Tt.fn[St].noConflict=function(){return Tt.fn[St]=Ot,Xt._jQueryInterface},Xt),qi=(en="modal",nn="."+(tn="bs.modal"),rn=($t=t).fn[en],on={backdrop:!0,keyboard:!0,focus:!0,show:!0},sn={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean",show:"boolean"},an={HIDE:"hide"+nn,HIDDEN:"hidden"+nn,SHOW:"show"+nn,SHOWN:"shown"+nn,FOCUSIN:"focusin"+nn,RESIZE:"resize"+nn,CLICK_DISMISS:"click.dismiss"+nn,KEYDOWN_DISMISS:"keydown.dismiss"+nn,MOUSEUP_DISMISS:"mouseup.dismiss"+nn,MOUSEDOWN_DISMISS:"mousedown.dismiss"+nn,CLICK_DATA_API:"click"+nn+".data-api"},ln="modal-scrollbar-measure",cn="modal-backdrop",un="modal-open",fn="fade",hn="show",dn=".modal-dialog",pn='[data-toggle="modal"]',mn='[data-dismiss="modal"]',gn=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",_n=".sticky-top",vn=function(){function r(e,t){this._config=this._getConfig(t),this._element=e,this._dialog=e.querySelector(dn),this._backdrop=null,this._isShown=!1,this._isBodyOverflowing=!1,this._ignoreBackdropClick=!1,this._scrollbarWidth=0}var e=r.prototype;return e.toggle=function(e){return this._isShown?this.hide():this.show(e)},e.show=function(e){var t=this;if(!this._isTransitioning&&!this._isShown){$t(this._element).hasClass(fn)&&(this._isTransitioning=!0);var n=$t.Event(an.SHOW,{relatedTarget:e});$t(this._element).trigger(n),this._isShown||n.isDefaultPrevented()||(this._isShown=!0,this._checkScrollbar(),this._setScrollbar(),this._adjustDialog(),$t(document.body).addClass(un),this._setEscapeEvent(),this._setResizeEvent(),$t(this._element).on(an.CLICK_DISMISS,mn,function(e){return t.hide(e)}),$t(this._dialog).on(an.MOUSEDOWN_DISMISS,function(){$t(t._element).one(an.MOUSEUP_DISMISS,function(e){$t(e.target).is(t._element)&&(t._ignoreBackdropClick=!0)})}),this._showBackdrop(function(){return t._showElement(e)}))}},e.hide=function(e){var t=this;if(e&&e.preventDefault(),!this._isTransitioning&&this._isShown){var n=$t.Event(an.HIDE);if($t(this._element).trigger(n),this._isShown&&!n.isDefaultPrevented()){this._isShown=!1;var i=$t(this._element).hasClass(fn);if(i&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),$t(document).off(an.FOCUSIN),$t(this._element).removeClass(hn),$t(this._element).off(an.CLICK_DISMISS),$t(this._dialog).off(an.MOUSEDOWN_DISMISS),i){var r=we.getTransitionDurationFromElement(this._element);$t(this._element).one(we.TRANSITION_END,function(e){return t._hideModal(e)}).emulateTransitionEnd(r)}else this._hideModal()}}},e.dispose=function(){$t.removeData(this._element,tn),$t(window,document,this._element,this._backdrop).off(nn),this._config=null,this._element=null,this._dialog=null,this._backdrop=null,this._isShown=null,this._isBodyOverflowing=null,this._ignoreBackdropClick=null,this._scrollbarWidth=null},e.handleUpdate=function(){this._adjustDialog()},e._getConfig=function(e){return e=l({},on,e),we.typeCheckConfig(en,e,sn),e},e._showElement=function(e){var t=this,n=$t(this._element).hasClass(fn);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.appendChild(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.scrollTop=0,n&&we.reflow(this._element),$t(this._element).addClass(hn),this._config.focus&&this._enforceFocus();var i=$t.Event(an.SHOWN,{relatedTarget:e}),r=function(){t._config.focus&&t._element.focus(),t._isTransitioning=!1,$t(t._element).trigger(i)};if(n){var o=we.getTransitionDurationFromElement(this._element);$t(this._dialog).one(we.TRANSITION_END,r).emulateTransitionEnd(o)}else r()},e._enforceFocus=function(){var t=this;$t(document).off(an.FOCUSIN).on(an.FOCUSIN,function(e){document!==e.target&&t._element!==e.target&&0===$t(t._element).has(e.target).length&&t._element.focus()})},e._setEscapeEvent=function(){var t=this;this._isShown&&this._config.keyboard?$t(this._element).on(an.KEYDOWN_DISMISS,function(e){27===e.which&&(e.preventDefault(),t.hide())}):this._isShown||$t(this._element).off(an.KEYDOWN_DISMISS)},e._setResizeEvent=function(){var t=this;this._isShown?$t(window).on(an.RESIZE,function(e){return t.handleUpdate(e)}):$t(window).off(an.RESIZE)},e._hideModal=function(){var e=this;this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._isTransitioning=!1,this._showBackdrop(function(){$t(document.body).removeClass(un),e._resetAdjustments(),e._resetScrollbar(),$t(e._element).trigger(an.HIDDEN)})},e._removeBackdrop=function(){this._backdrop&&($t(this._backdrop).remove(),this._backdrop=null)},e._showBackdrop=function(e){var t=this,n=$t(this._element).hasClass(fn)?fn:"";if(this._isShown&&this._config.backdrop){if(this._backdrop=document.createElement("div"),this._backdrop.className=cn,n&&this._backdrop.classList.add(n),$t(this._backdrop).appendTo(document.body),$t(this._element).on(an.CLICK_DISMISS,function(e){t._ignoreBackdropClick?t._ignoreBackdropClick=!1:e.target===e.currentTarget&&("static"===t._config.backdrop?t._element.focus():t.hide())}),n&&we.reflow(this._backdrop),$t(this._backdrop).addClass(hn),!e)return;if(!n)return void e();var i=we.getTransitionDurationFromElement(this._backdrop);$t(this._backdrop).one(we.TRANSITION_END,e).emulateTransitionEnd(i)}else if(!this._isShown&&this._backdrop){$t(this._backdrop).removeClass(hn);var r=function(){t._removeBackdrop(),e&&e()};if($t(this._element).hasClass(fn)){var o=we.getTransitionDurationFromElement(this._backdrop);$t(this._backdrop).one(we.TRANSITION_END,r).emulateTransitionEnd(o)}else r()}else e&&e()},e._adjustDialog=function(){var e=this._element.scrollHeight>document.documentElement.clientHeight;!this._isBodyOverflowing&&e&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!e&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},e._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},e._checkScrollbar=function(){var e=document.body.getBoundingClientRect();this._isBodyOverflowing=e.left+e.right<window.innerWidth,this._scrollbarWidth=this._getScrollbarWidth()},e._setScrollbar=function(){var r=this;if(this._isBodyOverflowing){var e=[].slice.call(document.querySelectorAll(gn)),t=[].slice.call(document.querySelectorAll(_n));$t(e).each(function(e,t){var n=t.style.paddingRight,i=$t(t).css("padding-right");$t(t).data("padding-right",n).css("padding-right",parseFloat(i)+r._scrollbarWidth+"px")}),$t(t).each(function(e,t){var n=t.style.marginRight,i=$t(t).css("margin-right");$t(t).data("margin-right",n).css("margin-right",parseFloat(i)-r._scrollbarWidth+"px")});var n=document.body.style.paddingRight,i=$t(document.body).css("padding-right");$t(document.body).data("padding-right",n).css("padding-right",parseFloat(i)+this._scrollbarWidth+"px")}},e._resetScrollbar=function(){var e=[].slice.call(document.querySelectorAll(gn));$t(e).each(function(e,t){var n=$t(t).data("padding-right");$t(t).removeData("padding-right"),t.style.paddingRight=n||""});var t=[].slice.call(document.querySelectorAll(""+_n));$t(t).each(function(e,t){var n=$t(t).data("margin-right");"undefined"!=typeof n&&$t(t).css("margin-right",n).removeData("margin-right")});var n=$t(document.body).data("padding-right");$t(document.body).removeData("padding-right"),document.body.style.paddingRight=n||""},e._getScrollbarWidth=function(){var e=document.createElement("div");e.className=ln,document.body.appendChild(e);var t=e.getBoundingClientRect().width-e.clientWidth;return document.body.removeChild(e),t},r._jQueryInterface=function(n,i){return this.each(function(){var e=$t(this).data(tn),t=l({},on,$t(this).data(),"object"==typeof n&&n?n:{});if(e||(e=new r(this,t),$t(this).data(tn,e)),"string"==typeof n){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n](i)}else t.show&&e.show(i)})},s(r,null,[{key:"VERSION",get:function(){return"4.1.3"}},{key:"Default",get:function(){return on}}]),r}(),$t(document).on(an.CLICK_DATA_API,pn,function(e){var t,n=this,i=we.getSelectorFromElement(this);i&&(t=document.querySelector(i));var r=$t(t).data(tn)?"toggle":l({},$t(t).data(),$t(this).data());"A"!==this.tagName&&"AREA"!==this.tagName||e.preventDefault();var o=$t(t).one(an.SHOW,function(e){e.isDefaultPrevented()||o.one(an.HIDDEN,function(){$t(n).is(":visible")&&n.focus()})});vn._jQueryInterface.call($t(t),r,this)}),$t.fn[en]=vn._jQueryInterface,$t.fn[en].Constructor=vn,$t.fn[en].noConflict=function(){return $t.fn[en]=rn,vn._jQueryInterface},vn),Ki=(En="tooltip",wn="."+(bn="bs.tooltip"),Cn=(yn=t).fn[En],Tn="bs-tooltip",Sn=new RegExp("(^|\\s)"+Tn+"\\S+","g"),In={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!(An={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"}),selector:!(Dn={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)"}),placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent"},Nn="out",kn={HIDE:"hide"+wn,HIDDEN:"hidden"+wn,SHOW:(On="show")+wn,SHOWN:"shown"+wn,INSERTED:"inserted"+wn,CLICK:"click"+wn,FOCUSIN:"focusin"+wn,FOCUSOUT:"focusout"+wn,MOUSEENTER:"mouseenter"+wn,MOUSELEAVE:"mouseleave"+wn},xn="fade",Pn="show",Ln=".tooltip-inner",jn=".arrow",Hn="hover",Mn="focus",Fn="click",Wn="manual",Rn=function(){function i(e,t){if("undefined"==typeof Ct)throw new TypeError("Bootstrap tooltips require Popper.js (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=e,this.config=this._getConfig(t),this.tip=null,this._setListeners()}var e=i.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(e){if(this._isEnabled)if(e){var t=this.constructor.DATA_KEY,n=yn(e.currentTarget).data(t);n||(n=new this.constructor(e.currentTarget,this._getDelegateConfig()),yn(e.currentTarget).data(t,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(yn(this.getTipElement()).hasClass(Pn))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),yn.removeData(this.element,this.constructor.DATA_KEY),yn(this.element).off(this.constructor.EVENT_KEY),yn(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&yn(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===yn(this.element).css("display"))throw new Error("Please use show on visible elements");var e=yn.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){yn(this.element).trigger(e);var n=yn.contains(this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!n)return;var i=this.getTipElement(),r=we.getUID(this.constructor.NAME);i.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&yn(i).addClass(xn);var o="function"==typeof this.config.placement?this.config.placement.call(this,i,this.element):this.config.placement,s=this._getAttachment(o);this.addAttachmentClass(s);var a=!1===this.config.container?document.body:yn(document).find(this.config.container);yn(i).data(this.constructor.DATA_KEY,this),yn.contains(this.element.ownerDocument.documentElement,this.tip)||yn(i).appendTo(a),yn(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new Ct(this.element,i,{placement:s,modifiers:{offset:{offset:this.config.offset},flip:{behavior:this.config.fallbackPlacement},arrow:{element:jn},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(e){e.originalPlacement!==e.placement&&t._handlePopperPlacementChange(e)},onUpdate:function(e){t._handlePopperPlacementChange(e)}}),yn(i).addClass(Pn),"ontouchstart"in document.documentElement&&yn(document.body).children().on("mouseover",null,yn.noop);var l=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,yn(t.element).trigger(t.constructor.Event.SHOWN),e===Nn&&t._leave(null,t)};if(yn(this.tip).hasClass(xn)){var c=we.getTransitionDurationFromElement(this.tip);yn(this.tip).one(we.TRANSITION_END,l).emulateTransitionEnd(c)}else l()}},e.hide=function(e){var t=this,n=this.getTipElement(),i=yn.Event(this.constructor.Event.HIDE),r=function(){t._hoverState!==On&&n.parentNode&&n.parentNode.removeChild(n),t._cleanTipClass(),t.element.removeAttribute("aria-describedby"),yn(t.element).trigger(t.constructor.Event.HIDDEN),null!==t._popper&&t._popper.destroy(),e&&e()};if(yn(this.element).trigger(i),!i.isDefaultPrevented()){if(yn(n).removeClass(Pn),"ontouchstart"in document.documentElement&&yn(document.body).children().off("mouseover",null,yn.noop),this._activeTrigger[Fn]=!1,this._activeTrigger[Mn]=!1,this._activeTrigger[Hn]=!1,yn(this.tip).hasClass(xn)){var o=we.getTransitionDurationFromElement(n);yn(n).one(we.TRANSITION_END,r).emulateTransitionEnd(o)}else r();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(e){yn(this.getTipElement()).addClass(Tn+"-"+e)},e.getTipElement=function(){return this.tip=this.tip||yn(this.config.template)[0],this.tip},e.setContent=function(){var e=this.getTipElement();this.setElementContent(yn(e.querySelectorAll(Ln)),this.getTitle()),yn(e).removeClass(xn+" "+Pn)},e.setElementContent=function(e,t){var n=this.config.html;"object"==typeof t&&(t.nodeType||t.jquery)?n?yn(t).parent().is(e)||e.empty().append(t):e.text(yn(t).text()):e[n?"html":"text"](t)},e.getTitle=function(){var e=this.element.getAttribute("data-original-title");return e||(e="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),e},e._getAttachment=function(e){return An[e.toUpperCase()]},e._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(e){if("click"===e)yn(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(e){return i.toggle(e)});else if(e!==Wn){var t=e===Hn?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=e===Hn?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;yn(i.element).on(t,i.config.selector,function(e){return i._enter(e)}).on(n,i.config.selector,function(e){return i._leave(e)})}yn(i.element).closest(".modal").on("hide.bs.modal",function(){return i.hide()})}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var e=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==e)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(e,t){var n=this.constructor.DATA_KEY;(t=t||yn(e.currentTarget).data(n))||(t=new this.constructor(e.currentTarget,this._getDelegateConfig()),yn(e.currentTarget).data(n,t)),e&&(t._activeTrigger["focusin"===e.type?Mn:Hn]=!0),yn(t.getTipElement()).hasClass(Pn)||t._hoverState===On?t._hoverState=On:(clearTimeout(t._timeout),t._hoverState=On,t.config.delay&&t.config.delay.show?t._timeout=setTimeout(function(){t._hoverState===On&&t.show()},t.config.delay.show):t.show())},e._leave=function(e,t){var n=this.constructor.DATA_KEY;(t=t||yn(e.currentTarget).data(n))||(t=new this.constructor(e.currentTarget,this._getDelegateConfig()),yn(e.currentTarget).data(n,t)),e&&(t._activeTrigger["focusout"===e.type?Mn:Hn]=!1),t._isWithActiveTrigger()||(clearTimeout(t._timeout),t._hoverState=Nn,t.config.delay&&t.config.delay.hide?t._timeout=setTimeout(function(){t._hoverState===Nn&&t.hide()},t.config.delay.hide):t.hide())},e._isWithActiveTrigger=function(){for(var e in this._activeTrigger)if(this._activeTrigger[e])return!0;return!1},e._getConfig=function(e){return"number"==typeof(e=l({},this.constructor.Default,yn(this.element).data(),"object"==typeof e&&e?e:{})).delay&&(e.delay={show:e.delay,hide:e.delay}),"number"==typeof e.title&&(e.title=e.title.toString()),"number"==typeof e.content&&(e.content=e.content.toString()),we.typeCheckConfig(En,e,this.constructor.DefaultType),e},e._getDelegateConfig=function(){var e={};if(this.config)for(var t in this.config)this.constructor.Default[t]!==this.config[t]&&(e[t]=this.config[t]);return e},e._cleanTipClass=function(){var e=yn(this.getTipElement()),t=e.attr("class").match(Sn);null!==t&&t.length&&e.removeClass(t.join(""))},e._handlePopperPlacementChange=function(e){var t=e.instance;this.tip=t.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(e.placement))},e._fixTransition=function(){var e=this.getTipElement(),t=this.config.animation;null===e.getAttribute("x-placement")&&(yn(e).removeClass(xn),this.config.animation=!1,this.hide(),this.show(),this.config.animation=t)},i._jQueryInterface=function(n){return this.each(function(){var e=yn(this).data(bn),t="object"==typeof n&&n;if((e||!/dispose|hide/.test(n))&&(e||(e=new i(this,t),yn(this).data(bn,e)),"string"==typeof n)){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.1.3"}},{key:"Default",get:function(){return In}},{key:"NAME",get:function(){return En}},{key:"DATA_KEY",get:function(){return bn}},{key:"Event",get:function(){return kn}},{key:"EVENT_KEY",get:function(){return wn}},{key:"DefaultType",get:function(){return Dn}}]),i}(),yn.fn[En]=Rn._jQueryInterface,yn.fn[En].Constructor=Rn,yn.fn[En].noConflict=function(){return yn.fn[En]=Cn,Rn._jQueryInterface},Rn),Qi=(Bn="popover",Kn="."+(qn="bs.popover"),Qn=(Un=t).fn[Bn],Yn="bs-popover",Vn=new RegExp("(^|\\s)"+Yn+"\\S+","g"),zn=l({},Ki.Default,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'}),Gn=l({},Ki.DefaultType,{content:"(string|element|function)"}),Jn="fade",Xn=".popover-header",$n=".popover-body",ei={HIDE:"hide"+Kn,HIDDEN:"hidden"+Kn,SHOW:(Zn="show")+Kn,SHOWN:"shown"+Kn,INSERTED:"inserted"+Kn,CLICK:"click"+Kn,FOCUSIN:"focusin"+Kn,FOCUSOUT:"focusout"+Kn,MOUSEENTER:"mouseenter"+Kn,MOUSELEAVE:"mouseleave"+Kn},ti=function(e){var t,n;function i(){return e.apply(this,arguments)||this}n=e,(t=i).prototype=Object.create(n.prototype),(t.prototype.constructor=t).__proto__=n;var r=i.prototype;return r.isWithContent=function(){return this.getTitle()||this._getContent()},r.addAttachmentClass=function(e){Un(this.getTipElement()).addClass(Yn+"-"+e)},r.getTipElement=function(){return this.tip=this.tip||Un(this.config.template)[0],this.tip},r.setContent=function(){var e=Un(this.getTipElement());this.setElementContent(e.find(Xn),this.getTitle());var t=this._getContent();"function"==typeof t&&(t=t.call(this.element)),this.setElementContent(e.find($n),t),e.removeClass(Jn+" "+Zn)},r._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},r._cleanTipClass=function(){var e=Un(this.getTipElement()),t=e.attr("class").match(Vn);null!==t&&0<t.length&&e.removeClass(t.join(""))},i._jQueryInterface=function(n){return this.each(function(){var e=Un(this).data(qn),t="object"==typeof n?n:null;if((e||!/destroy|hide/.test(n))&&(e||(e=new i(this,t),Un(this).data(qn,e)),"string"==typeof n)){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.1.3"}},{key:"Default",get:function(){return zn}},{key:"NAME",get:function(){return Bn}},{key:"DATA_KEY",get:function(){return qn}},{key:"Event",get:function(){return ei}},{key:"EVENT_KEY",get:function(){return Kn}},{key:"DefaultType",get:function(){return Gn}}]),i}(Ki),Un.fn[Bn]=ti._jQueryInterface,Un.fn[Bn].Constructor=ti,Un.fn[Bn].noConflict=function(){return Un.fn[Bn]=Qn,ti._jQueryInterface},ti),Yi=(ii="scrollspy",oi="."+(ri="bs.scrollspy"),si=(ni=t).fn[ii],ai={offset:10,method:"auto",target:""},li={offset:"number",method:"string",target:"(string|element)"},ci={ACTIVATE:"activate"+oi,SCROLL:"scroll"+oi,LOAD_DATA_API:"load"+oi+".data-api"},ui="dropdown-item",fi="active",hi='[data-spy="scroll"]',di=".active",pi=".nav, .list-group",mi=".nav-link",gi=".nav-item",_i=".list-group-item",vi=".dropdown",yi=".dropdown-item",Ei=".dropdown-toggle",bi="offset",wi="position",Ci=function(){function n(e,t){var n=this;this._element=e,this._scrollElement="BODY"===e.tagName?window:e,this._config=this._getConfig(t),this._selector=this._config.target+" "+mi+","+this._config.target+" "+_i+","+this._config.target+" "+yi,this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,ni(this._scrollElement).on(ci.SCROLL,function(e){return n._process(e)}),this.refresh(),this._process()}var e=n.prototype;return e.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?bi:wi,r="auto"===this._config.method?e:this._config.method,o=r===wi?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map(function(e){var t,n=we.getSelectorFromElement(e);if(n&&(t=document.querySelector(n)),t){var i=t.getBoundingClientRect();if(i.width||i.height)return[ni(t)[r]().top+o,n]}return null}).filter(function(e){return e}).sort(function(e,t){return e[0]-t[0]}).forEach(function(e){t._offsets.push(e[0]),t._targets.push(e[1])})},e.dispose=function(){ni.removeData(this._element,ri),ni(this._scrollElement).off(oi),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},e._getConfig=function(e){if("string"!=typeof(e=l({},ai,"object"==typeof e&&e?e:{})).target){var t=ni(e.target).attr("id");t||(t=we.getUID(ii),ni(e.target).attr("id",t)),e.target="#"+t}return we.typeCheckConfig(ii,e,li),e},e._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},e._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},e._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},e._process=function(){var e=this._getScrollTop()+this._config.offset,t=this._getScrollHeight(),n=this._config.offset+t-this._getOffsetHeight();if(this._scrollHeight!==t&&this.refresh(),n<=e){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&e<this._offsets[0]&&0<this._offsets[0])return this._activeTarget=null,void this._clear();for(var r=this._offsets.length;r--;){this._activeTarget!==this._targets[r]&&e>=this._offsets[r]&&("undefined"==typeof this._offsets[r+1]||e<this._offsets[r+1])&&this._activate(this._targets[r])}}},e._activate=function(t){this._activeTarget=t,this._clear();var e=this._selector.split(",");e=e.map(function(e){return e+'[data-target="'+t+'"],'+e+'[href="'+t+'"]'});var n=ni([].slice.call(document.querySelectorAll(e.join(","))));n.hasClass(ui)?(n.closest(vi).find(Ei).addClass(fi),n.addClass(fi)):(n.addClass(fi),n.parents(pi).prev(mi+", "+_i).addClass(fi),n.parents(pi).prev(gi).children(mi).addClass(fi)),ni(this._scrollElement).trigger(ci.ACTIVATE,{relatedTarget:t})},e._clear=function(){var e=[].slice.call(document.querySelectorAll(this._selector));ni(e).filter(di).removeClass(fi)},n._jQueryInterface=function(t){return this.each(function(){var e=ni(this).data(ri);if(e||(e=new n(this,"object"==typeof t&&t),ni(this).data(ri,e)),"string"==typeof t){if("undefined"==typeof e[t])throw new TypeError('No method named "'+t+'"');e[t]()}})},s(n,null,[{key:"VERSION",get:function(){return"4.1.3"}},{key:"Default",get:function(){return ai}}]),n}(),ni(window).on(ci.LOAD_DATA_API,function(){for(var e=[].slice.call(document.querySelectorAll(hi)),t=e.length;t--;){var n=ni(e[t]);Ci._jQueryInterface.call(n,n.data())}}),ni.fn[ii]=Ci._jQueryInterface,ni.fn[ii].Constructor=Ci,ni.fn[ii].noConflict=function(){return ni.fn[ii]=si,Ci._jQueryInterface},Ci),Vi=(Di="."+(Si="bs.tab"),Ai=(Ti=t).fn.tab,Ii={HIDE:"hide"+Di,HIDDEN:"hidden"+Di,SHOW:"show"+Di,SHOWN:"shown"+Di,CLICK_DATA_API:"click"+Di+".data-api"},Oi="dropdown-menu",Ni="active",ki="disabled",xi="fade",Pi="show",Li=".dropdown",ji=".nav, .list-group",Hi=".active",Mi="> li > .active",Fi='[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',Wi=".dropdown-toggle",Ri="> .dropdown-menu .active",Ui=function(){function i(e){this._element=e}var e=i.prototype;return e.show=function(){var n=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&Ti(this._element).hasClass(Ni)||Ti(this._element).hasClass(ki))){var e,i,t=Ti(this._element).closest(ji)[0],r=we.getSelectorFromElement(this._element);if(t){var o="UL"===t.nodeName?Mi:Hi;i=(i=Ti.makeArray(Ti(t).find(o)))[i.length-1]}var s=Ti.Event(Ii.HIDE,{relatedTarget:this._element}),a=Ti.Event(Ii.SHOW,{relatedTarget:i});if(i&&Ti(i).trigger(s),Ti(this._element).trigger(a),!a.isDefaultPrevented()&&!s.isDefaultPrevented()){r&&(e=document.querySelector(r)),this._activate(this._element,t);var l=function(){var e=Ti.Event(Ii.HIDDEN,{relatedTarget:n._element}),t=Ti.Event(Ii.SHOWN,{relatedTarget:i});Ti(i).trigger(e),Ti(n._element).trigger(t)};e?this._activate(e,e.parentNode,l):l()}}},e.dispose=function(){Ti.removeData(this._element,Si),this._element=null},e._activate=function(e,t,n){var i=this,r=("UL"===t.nodeName?Ti(t).find(Mi):Ti(t).children(Hi))[0],o=n&&r&&Ti(r).hasClass(xi),s=function(){return i._transitionComplete(e,r,n)};if(r&&o){var a=we.getTransitionDurationFromElement(r);Ti(r).one(we.TRANSITION_END,s).emulateTransitionEnd(a)}else s()},e._transitionComplete=function(e,t,n){if(t){Ti(t).removeClass(Pi+" "+Ni);var i=Ti(t.parentNode).find(Ri)[0];i&&Ti(i).removeClass(Ni),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!1)}if(Ti(e).addClass(Ni),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!0),we.reflow(e),Ti(e).addClass(Pi),e.parentNode&&Ti(e.parentNode).hasClass(Oi)){var r=Ti(e).closest(Li)[0];if(r){var o=[].slice.call(r.querySelectorAll(Wi));Ti(o).addClass(Ni)}e.setAttribute("aria-expanded",!0)}n&&n()},i._jQueryInterface=function(n){return this.each(function(){var e=Ti(this),t=e.data(Si);if(t||(t=new i(this),e.data(Si,t)),"string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.1.3"}}]),i}(),Ti(document).on(Ii.CLICK_DATA_API,Fi,function(e){e.preventDefault(),Ui._jQueryInterface.call(Ti(this),"show")}),Ti.fn.tab=Ui._jQueryInterface,Ti.fn.tab.Constructor=Ui,Ti.fn.tab.noConflict=function(){return Ti.fn.tab=Ai,Ui._jQueryInterface},Ui);!function(e){if("undefined"==typeof e)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var t=e.fn.jquery.split(" ")[0].split(".");if(t[0]<2&&t[1]<9||1===t[0]&&9===t[1]&&t[2]<1||4<=t[0])throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(t),e.Util=we,e.Alert=Ce,e.Button=Te,e.Carousel=Se,e.Collapse=De,e.Dropdown=Bi,e.Modal=qi,e.Popover=Qi,e.Scrollspy=Yi,e.Tab=Vi,e.Tooltip=Ki,Object.defineProperty(e,"__esModule",{value:!0})});
6 //# sourceMappingURL=bootstrap.bundle.min.js.map
+0
-7
docs/_static/bootstrap-4.1.3.min.css less more
0 /*!
1 * Bootstrap v4.1.3 (https://getbootstrap.com/)
2 * Copyright 2011-2018 The Bootstrap Authors
3 * Copyright 2011-2018 Twitter, Inc.
4 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-family:inherit;font-weight:500;line-height:1.2;color:inherit}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014 \00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#e83e8c;word-break:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;margin-bottom:1rem;background-color:transparent}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table .table{background-color:#fff}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-borderless tbody+tbody,.table-borderless td,.table-borderless th,.table-borderless thead th{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#212529;border-color:#32383e}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#212529}.table-dark td,.table-dark th,.table-dark thead th{border-color:#32383e}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(2.25rem + 2px);padding:.375rem .75rem;font-size:1rem;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.8125rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(2.875rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[multiple],select.form-control[size]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.custom-select.is-valid,.form-control.is-valid,.was-validated .custom-select:valid,.was-validated .form-control:valid{border-color:#28a745}.custom-select.is-valid:focus,.form-control.is-valid:focus,.was-validated .custom-select:valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip,.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip,.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip{display:block}.form-control-file.is-valid~.valid-feedback,.form-control-file.is-valid~.valid-tooltip,.was-validated .form-control-file:valid~.valid-feedback,.was-validated .form-control-file:valid~.valid-tooltip{display:block}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{background-color:#71dd8a}.custom-control-input.is-valid~.valid-feedback,.custom-control-input.is-valid~.valid-tooltip,.was-validated .custom-control-input:valid~.valid-feedback,.was-validated .custom-control-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(40,167,69,.25)}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label::after,.was-validated .custom-file-input:valid~.custom-file-label::after{border-color:inherit}.custom-file-input.is-valid~.valid-feedback,.custom-file-input.is-valid~.valid-tooltip,.was-validated .custom-file-input:valid~.valid-feedback,.was-validated .custom-file-input:valid~.valid-tooltip{display:block}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.custom-select.is-invalid,.form-control.is-invalid,.was-validated .custom-select:invalid,.was-validated .form-control:invalid{border-color:#dc3545}.custom-select.is-invalid:focus,.form-control.is-invalid:focus,.was-validated .custom-select:invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip,.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip,.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip{display:block}.form-control-file.is-invalid~.invalid-feedback,.form-control-file.is-invalid~.invalid-tooltip,.was-validated .form-control-file:invalid~.invalid-feedback,.was-validated .form-control-file:invalid~.invalid-tooltip{display:block}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{background-color:#efa2a9}.custom-control-input.is-invalid~.invalid-feedback,.custom-control-input.is-invalid~.invalid-tooltip,.was-validated .custom-control-input:invalid~.invalid-feedback,.was-validated .custom-control-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(220,53,69,.25)}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label::after,.was-validated .custom-file-input:invalid~.custom-file-label::after{border-color:inherit}.custom-file-input.is-invalid~.invalid-feedback,.custom-file-input.is-invalid~.invalid-tooltip,.was-validated .custom-file-input:invalid~.invalid-feedback,.was-validated .custom-file-input:invalid~.invalid-tooltip{display:block}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-ms-flexbox;display:flex;-ms-flex:0 0 auto;flex:0 0 auto;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .custom-select,.form-inline .input-group{width:auto}.form-inline .form-check{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:focus,.btn:hover{text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-primary{color:#007bff;background-color:transparent;background-image:none;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;background-color:transparent;background-image:none;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;background-color:transparent;background-image:none;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;background-color:transparent;background-image:none;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;background-color:transparent;background-image:none;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;background-color:transparent;background-image:none;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;background-color:transparent;background-image:none;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;background-color:transparent;background-image:none;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;background-color:transparent}.btn-link:hover{color:#0056b3;text-decoration:underline;background-color:transparent;border-color:transparent}.btn-link.focus,.btn-link:focus{text-decoration:underline;border-color:transparent;box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#6c757d;pointer-events:none}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{transition:opacity .15s linear}@media screen and (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media screen and (prefers-reduced-motion:reduce){.collapsing{transition:none}}.dropdown,.dropleft,.dropright,.dropup{position:relative}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropdown-menu-right{right:0;left:auto}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;width:0;height:0;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-ms-flex:0 1 auto;flex:0 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn+.btn-group,.btn-group-vertical .btn-group+.btn,.btn-group-vertical .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-ms-flex-direction:column;flex-direction:column;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control{margin-left:-1px}.input-group>.custom-file .custom-file-input:focus~.custom-file-label,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{height:calc(2.875rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{height:calc(1.8125rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:active~.custom-control-label::before{color:#fff;background-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#dee2e6}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background-repeat:no-repeat;background-position:center center;background-size:50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::before{background-color:#007bff}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::before{background-color:#007bff}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(2.25rem + 2px);padding:.375rem 1.75rem .375rem .75rem;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center;background-size:8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(128,189,255,.5)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{opacity:0}.custom-select-sm{height:calc(1.8125rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:75%}.custom-select-lg{height:calc(2.875rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:125%}.custom-file{position:relative;display:inline-block;width:100%;height:calc(2.25rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(2.25rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:focus~.custom-file-label::after{border-color:#80bdff}.custom-file-input:disabled~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(2.25rem + 2px);padding:.375rem .75rem;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:2.25rem;padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:1px solid #ced4da;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;padding-left:0;background-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-appearance:none;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-webkit-slider-thumb{transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#b3d7ff}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;-moz-appearance:none;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-moz-range-thumb{transition:none}}.custom-range::-moz-range-thumb:active{background-color:#b3d7ff}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#007bff;border:0;border-radius:1rem;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;appearance:none}@media screen and (prefers-reduced-motion:reduce){.custom-range::-ms-thumb{transition:none}}.custom-range::-ms-thumb:active{background-color:#b3d7ff}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media screen and (prefers-reduced-motion:reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar>.container,.navbar>.container-fluid{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-ms-flex-positive:1;flex-grow:1;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler:not(:disabled):not(.disabled){cursor:pointer}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{-ms-flex-flow:row nowrap;flex-flow:row nowrap;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img{width:100%;border-radius:calc(.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{display:-ms-flexbox;display:flex;-ms-flex:1 0 0%;flex:1 0 0%;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:first-child .card-header,.card-group>.card:first-child .card-img-top{border-top-right-radius:0}.card-group>.card:first-child .card-footer,.card-group>.card:first-child .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:last-child .card-header,.card-group>.card:last-child .card-img-top{border-top-left-radius:0}.card-group>.card:last-child .card-footer,.card-group>.card:last-child .card-img-bottom{border-bottom-left-radius:0}.card-group>.card:only-child{border-radius:.25rem}.card-group>.card:only-child .card-header,.card-group>.card:only-child .card-img-top{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-group>.card:only-child .card-footer,.card-group>.card:only-child .card-img-bottom{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-group>.card:not(:first-child):not(:last-child):not(:only-child){border-radius:0}.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-footer,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-header,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-top{border-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card{display:inline-block;width:100%}}.accordion .card:not(:first-of-type):not(:last-of-type){border-bottom:0;border-radius:0}.accordion .card:not(:first-of-type) .card-header:first-child{border-radius:0}.accordion .card:first-of-type{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion .card:last-of-type{border-top-left-radius:0;border-top-right-radius:0}.breadcrumb{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:2;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-link:not(:disabled):not(.disabled){cursor:pointer}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:1;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}.badge-primary[href]:focus,.badge-primary[href]:hover{color:#fff;text-decoration:none;background-color:#0062cc}.badge-secondary{color:#fff;background-color:#6c757d}.badge-secondary[href]:focus,.badge-secondary[href]:hover{color:#fff;text-decoration:none;background-color:#545b62}.badge-success{color:#fff;background-color:#28a745}.badge-success[href]:focus,.badge-success[href]:hover{color:#fff;text-decoration:none;background-color:#1e7e34}.badge-info{color:#fff;background-color:#17a2b8}.badge-info[href]:focus,.badge-info[href]:hover{color:#fff;text-decoration:none;background-color:#117a8b}.badge-warning{color:#212529;background-color:#ffc107}.badge-warning[href]:focus,.badge-warning[href]:hover{color:#212529;text-decoration:none;background-color:#d39e00}.badge-danger{color:#fff;background-color:#dc3545}.badge-danger[href]:focus,.badge-danger[href]:hover{color:#fff;text-decoration:none;background-color:#bd2130}.badge-light{color:#212529;background-color:#f8f9fa}.badge-light[href]:focus,.badge-light[href]:hover{color:#212529;text-decoration:none;background-color:#dae0e5}.badge-dark{color:#fff;background-color:#343a40}.badge-dark[href]:focus,.badge-dark[href]:hover{color:#fff;text-decoration:none;background-color:#1d2124}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;color:#fff;text-align:center;white-space:nowrap;background-color:#007bff;transition:width .6s ease}@media screen and (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start}.media-body{-ms-flex:1;flex:1}.list-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item:focus,.list-group-item:hover{z-index:1;text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:not(:disabled):not(.disabled){cursor:pointer}.close:not(:disabled):not(.disabled):focus,.close:not(:disabled):not(.disabled):hover{color:#000;text-decoration:none;opacity:.75}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-25%);transform:translate(0,-25%)}@media screen and (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{-webkit-transform:translate(0,0);transform:translate(0,0)}.modal-dialog-centered{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;min-height:calc(100% - (.5rem * 2))}.modal-dialog-centered::before{display:block;height:calc(100vh - (.5rem * 2));content:""}.modal-content{position:relative;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-ms-flexbox;display:flex;-ms-flex-align:start;align-items:flex-start;-ms-flex-pack:justify;justify-content:space-between;padding:1rem;border-bottom:1px solid #e9ecef;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end;padding:1rem;border-top:1px solid #e9ecef}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-centered{min-height:calc(100% - (1.75rem * 2))}.modal-dialog-centered::before{height:calc(100vh - (1.75rem * 2))}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg{max-width:800px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top] .arrow,.bs-popover-top .arrow{bottom:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=top] .arrow::after,.bs-popover-auto[x-placement^=top] .arrow::before,.bs-popover-top .arrow::after,.bs-popover-top .arrow::before{border-width:.5rem .5rem 0}.bs-popover-auto[x-placement^=top] .arrow::before,.bs-popover-top .arrow::before{bottom:0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top] .arrow::after,.bs-popover-top .arrow::after{bottom:1px;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right] .arrow,.bs-popover-right .arrow{left:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right] .arrow::after,.bs-popover-auto[x-placement^=right] .arrow::before,.bs-popover-right .arrow::after,.bs-popover-right .arrow::before{border-width:.5rem .5rem .5rem 0}.bs-popover-auto[x-placement^=right] .arrow::before,.bs-popover-right .arrow::before{left:0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right] .arrow::after,.bs-popover-right .arrow::after{left:1px;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom] .arrow,.bs-popover-bottom .arrow{top:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=bottom] .arrow::after,.bs-popover-auto[x-placement^=bottom] .arrow::before,.bs-popover-bottom .arrow::after,.bs-popover-bottom .arrow::before{border-width:0 .5rem .5rem .5rem}.bs-popover-auto[x-placement^=bottom] .arrow::before,.bs-popover-bottom .arrow::before{top:0;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom] .arrow::after,.bs-popover-bottom .arrow::after{top:1px;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left] .arrow,.bs-popover-left .arrow{right:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left] .arrow::after,.bs-popover-auto[x-placement^=left] .arrow::before,.bs-popover-left .arrow::after,.bs-popover-left .arrow::before{border-width:.5rem 0 .5rem .5rem}.bs-popover-auto[x-placement^=left] .arrow::before,.bs-popover-left .arrow::before{right:0;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left] .arrow::after,.bs-popover-left .arrow::after{right:1px;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;color:inherit;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-item{position:relative;display:none;-ms-flex-align:center;align-items:center;width:100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block;transition:-webkit-transform .6s ease;transition:transform .6s ease;transition:transform .6s ease,-webkit-transform .6s ease}@media screen and (prefers-reduced-motion:reduce){.carousel-item-next,.carousel-item-prev,.carousel-item.active{transition:none}}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translateX(0);transform:translateX(0)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.active.carousel-item-right,.carousel-item-next{-webkit-transform:translateX(100%);transform:translateX(100%)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.active.carousel-item-right,.carousel-item-next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translateX(-100%);transform:translateX(-100%)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.carousel-fade .carousel-item{opacity:0;transition-duration:.6s;transition-property:opacity}.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right,.carousel-fade .carousel-item.active{opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{opacity:0}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev,.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active{-webkit-transform:translateX(0);transform:translateX(0)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-prev,.carousel-fade .carousel-item-next,.carousel-fade .carousel-item-prev,.carousel-fade .carousel-item.active{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:transparent no-repeat center center;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{position:relative;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:rgba(255,255,255,.5)}.carousel-indicators li::before{position:absolute;top:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators li::after{position:absolute;bottom:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-circle{border-radius:50%!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 .125rem .25rem rgba(0,0,0,.075)!important}.shadow{box-shadow:0 .5rem 1rem rgba(0,0,0,.15)!important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,.175)!important}.shadow-none{box-shadow:none!important}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0062cc!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#545b62!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#1e7e34!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#117a8b!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#d39e00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#bd2130!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#dae0e5!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#1d2124!important}.text-body{color:#212529!important}.text-muted{color:#6c757d!important}.text-black-50{color:rgba(0,0,0,.5)!important}.text-white-50{color:rgba(255,255,255,.5)!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #dee2e6!important}.table-dark{color:inherit}.table-dark tbody+tbody,.table-dark td,.table-dark th,.table-dark thead th{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}}
6 /*# sourceMappingURL=bootstrap.min.css.map */
+0
-78
docs/_static/instaloader.css less more
0 @import url(bootstrap-4.1.3.min.css);
1 a {
2 color: #008d06; }
3 a:hover, a.current, a.active {
4 color: #f48400; }
5 a.current, a.active {
6 font-weight: 500; }
7
8 .doc-sidebar a:hover, .modal-body a:hover {
9 text-decoration: none; }
10
11 code {
12 color: #212529; }
13
14 .highlight {
15 border-radius: 0.3em; }
16 .highlight pre {
17 padding: 0.7em;
18 color: #fff; }
19 .highlight .c1 {
20 color: #666; }
21 .highlight .k, .highlight .kn, .highlight .ow {
22 color: #008d06; }
23 .highlight .nb, .highlight .ne, .highlight .nf, .highlight .vm {
24 color: #f48400; }
25 .highlight .s1, .highlight .s2, .highlight .sa, .highlight .se, .highlight .si, .highlight .mi {
26 color: #ff7efd; }
27 .highlight .c1, .highlight .nf, .highlight .sa, .highlight .se, .highlight .si {
28 font-style: italic; }
29 .highlight .k, .highlight .kn, .highlight .ow {
30 font-weight: bold; }
31
32 .doc-content {
33 padding-top: 0.5em;
34 top: 3.5625em;
35 position: fixed;
36 bottom: 0;
37 overflow-y: auto; }
38
39 .doc-sidebar {
40 position: fixed;
41 padding-top: 0.5em;
42 top: 3.5625em;
43 bottom: 0;
44 right: 0;
45 overflow-y: auto; }
46 .doc-sidebar ul {
47 list-style-type: none;
48 padding-left: 1em; }
49 .doc-sidebar ul.current {
50 padding-left: 0; }
51 .doc-sidebar li {
52 padding-top: 0.2em;
53 padding-bottom: 0.2em; }
54
55 .admonition {
56 border-radius: 0.3em;
57 border: 1px solid #ccc;
58 background-color: #f8f9fa; }
59 .admonition .admonition-title {
60 color: #ff7efd; }
61
62 .topic {
63 border-radius: 0.3em;
64 background-color: #f8f9fa; }
65
66 .nav-link {
67 padding-top: 0;
68 padding-bottom: 0; }
69
70 .btn-success {
71 background-color: #008d06;
72 border-color: #008d06; }
73 .btn-success:hover {
74 background-color: #f48400;
75 border-color: #f48400; }
76
77 /*# sourceMappingURL=instaloader.css.map */
+0
-22
docs/_static/instaloader.js less more
0 $(function () {
1 $('[data-toggle="tooltip"]').tooltip();
2
3 $('.doc-sidebar > ul > li.current').attr("id", "localtoc");
4 $('#localtoc ul').addClass("nav flex-column");
5 $('#localtoc ul li').addClass("nav-item");
6 $('#localtoc ul li a').addClass("nav-link");
7 $('.doc-content').scrollspy({target: '#localtoc'});
8
9 const top_href = '#' + $('.section:first').attr("id");
10 $('#localtoc > a.current').attr("href", top_href);
11
12 $('#navbarToc a').on("click", function () {
13 const href = $(this).attr("href");
14 if (href === '#') {
15 window.location.href = top_href;
16 } else {
17 window.location.href = href;
18 }
19 $('#navbarToc').modal('hide');
20 });
21 });
+0
-124
docs/_static/instaloader.scss less more
0 @import 'bootstrap-4.1.3.min.css';
1
2 $color_instaloader_main: #008d06;
3 $color_instaloader_accent: #f48400;
4 $color_instaloader_hyper: #ff7efd;
5 $color_normal_text: #212529;
6 $color_light_bg: #f8f9fa;
7
8 a {
9 color: $color_instaloader_main;
10
11 &:hover, &.current, &.active {
12 color: $color_instaloader_accent;
13 }
14
15 &.current, &.active {
16 font-weight: 500;
17 }
18 }
19
20 .doc-sidebar, .modal-body {
21 a:hover {
22 text-decoration: none
23 }
24 }
25
26 code {
27 color: $color_normal_text;
28 }
29
30 .highlight {
31 border-radius: 0.3em;
32
33 pre {
34 padding: 0.7em;
35 color: #fff;
36 }
37
38 .c1 {
39 color: #666;
40 }
41
42 .k, .kn, .ow {
43 color: $color_instaloader_main
44 }
45
46 .nb, .ne, .nf, .vm {
47 color: $color_instaloader_accent
48 }
49
50 .s1, .s2, .sa, .se, .si, .mi {
51 color: $color_instaloader_hyper
52 }
53
54 .c1, .nf, .sa, .se, .si {
55 font-style: italic;
56 }
57
58 .k, .kn, .ow {
59 font-weight: bold
60 }
61 }
62
63 .doc-content {
64 padding-top: 0.5em;
65 top: 3.5625em;
66 position: fixed;
67 bottom: 0;
68 overflow-y: auto;
69 }
70
71 .doc-sidebar {
72 position: fixed;
73 padding-top: 0.5em;
74 top: 3.5625em;
75 bottom: 0;
76 right: 0;
77 overflow-y: auto;
78
79 ul {
80 list-style-type: none;
81 padding-left: 1em;
82
83 &.current {
84 padding-left: 0;
85 }
86 }
87
88 li {
89 padding-top: 0.2em;
90 padding-bottom: 0.2em;
91
92 }
93 }
94
95 .admonition {
96 border-radius: 0.3em;
97 border: 1px solid #ccc;
98 background-color: $color_light_bg;
99
100 .admonition-title {
101 color: $color_instaloader_hyper;
102 }
103 }
104
105 .topic {
106 border-radius: 0.3em;
107 background-color: $color_light_bg;
108 }
109
110 .nav-link {
111 padding-top: 0;
112 padding-bottom: 0;
113 }
114
115 .btn-success {
116 background-color: $color_instaloader_main;
117 border-color: $color_instaloader_main;
118
119 &:hover {
120 background-color: $color_instaloader_accent;
121 border-color: $color_instaloader_accent;
122 }
123 }
0 :root{--primary: #008306;--light: #f8f9fa;--breakpoint-xs: 0;--breakpoint-sm: 576px;--breakpoint-md: 768px;--breakpoint-lg: 992px;--breakpoint-xl: 1200px;--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*::before,*::after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0 !important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-original-title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}a{color:#008306;text-decoration:none;background-color:transparent}a:hover{color:#e57c00;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button:not(:disabled),[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled){cursor:pointer}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none !important}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}h1,.h1{font-size:2.5rem}h2,.h2{font-size:2rem}h3,.h3{font-size:1.75rem}h4,.h4{font-size:1.5rem}h5,.h5{font-size:1.25rem}h6,.h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}small,.small{font-size:80%;font-weight:400}mark,.mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"— "}code{font-size:87.5%;color:#212529;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media(min-width: 576px){.container{max-width:540px}}@media(min-width: 768px){.container{max-width:720px}}@media(min-width: 992px){.container{max-width:960px}}@media(min-width: 1200px){.container{max-width:1140px}}.container-fluid,.container-xl,.container-lg,.container-md,.container-sm{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media(min-width: 576px){.container-sm,.container{max-width:540px}}@media(min-width: 768px){.container-md,.container-sm,.container{max-width:720px}}@media(min-width: 992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media(min-width: 1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}.row{display:flex;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col-xl,.col-xl-auto,.col-xl-12,.col-xl-11,.col-xl-10,.col-xl-9,.col-xl-8,.col-xl-7,.col-xl-6,.col-xl-5,.col-xl-4,.col-xl-3,.col-xl-2,.col-xl-1,.col-lg,.col-lg-auto,.col-lg-12,.col-lg-11,.col-lg-10,.col-lg-9,.col-lg-8,.col-lg-7,.col-lg-6,.col-lg-5,.col-lg-4,.col-lg-3,.col-lg-2,.col-lg-1,.col-md,.col-md-auto,.col-md-12,.col-md-11,.col-md-10,.col-md-9,.col-md-8,.col-md-7,.col-md-6,.col-md-5,.col-md-4,.col-md-3,.col-md-2,.col-md-1,.col-sm,.col-sm-auto,.col-sm-12,.col-sm-11,.col-sm-10,.col-sm-9,.col-sm-8,.col-sm-7,.col-sm-6,.col-sm-5,.col-sm-4,.col-sm-3,.col-sm-2,.col-sm-1,.col,.col-auto,.col-12,.col-11,.col-10,.col-9,.col-8,.col-7,.col-6,.col-5,.col-4,.col-3,.col-2,.col-1{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-1>*{flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-4>*{flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-auto{flex:0 0 auto;width:auto;max-width:100%}.col-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-3{flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-6{flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-9{flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-12{flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.3333333333%}.offset-2{margin-left:16.6666666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.3333333333%}.offset-5{margin-left:41.6666666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.3333333333%}.offset-8{margin-left:66.6666666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.3333333333%}.offset-11{margin-left:91.6666666667%}@media(min-width: 576px){.col-sm{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-sm-4>*{flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-auto{flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-sm-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-3{flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-sm-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-sm-6{flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-sm-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-sm-9{flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-sm-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-sm-12{flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-11{margin-left:91.6666666667%}}@media(min-width: 768px){.col-md{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-md-4>*{flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-auto{flex:0 0 auto;width:auto;max-width:100%}.col-md-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-md-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-3{flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-md-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-md-6{flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-md-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-md-9{flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-md-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-md-12{flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.3333333333%}.offset-md-2{margin-left:16.6666666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.3333333333%}.offset-md-5{margin-left:41.6666666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.3333333333%}.offset-md-8{margin-left:66.6666666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.3333333333%}.offset-md-11{margin-left:91.6666666667%}}@media(min-width: 992px){.col-lg{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-lg-4>*{flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-auto{flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-lg-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-3{flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-lg-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-lg-6{flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-lg-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-lg-9{flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-lg-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-lg-12{flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-11{margin-left:91.6666666667%}}@media(min-width: 1200px){.col-xl{flex-basis:0;flex-grow:1;min-width:0;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.3333333333%;max-width:33.3333333333%}.row-cols-xl-4>*{flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-auto{flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-xl-2{flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-3{flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-xl-5{flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-xl-6{flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-xl-8{flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-xl-9{flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-xl-11{flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-xl-12{flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.3333333333%}.offset-xl-2{margin-left:16.6666666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.3333333333%}.offset-xl-5{margin-left:41.6666666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.3333333333%}.offset-xl-8{margin-left:66.6666666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.3333333333%}.offset-xl-11{margin-left:91.6666666667%}}.form-control{display:block;width:100%;height:calc(1.5em + 0.75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#03ff0e;outline:0;box-shadow:0 0 0 .2rem rgba(0,131,6,.25)}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{-webkit-appearance:none;-moz-appearance:none;appearance:none}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(0.375rem + 1px);padding-bottom:calc(0.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(0.5rem + 1px);padding-bottom:calc(0.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(0.25rem + 1px);padding-bottom:calc(0.25rem + 1px);font-size:0.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + 0.5rem + 2px);padding:.25rem .5rem;font-size:0.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[size],select.form-control[multiple]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:flex;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input[disabled]~.form-check-label,.form-check-input:disabled~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:inline-flex;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.75rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,.9);border-radius:.25rem}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#28a745;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .custom-select:valid,.custom-select.is-valid{border-color:#28a745;padding-right:calc(0.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .custom-select:valid:focus,.custom-select.is-valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated .form-check-input:valid~.form-check-label,.form-check-input.is-valid~.form-check-label{color:#28a745}.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip,.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip{display:block}.was-validated .custom-control-input:valid~.custom-control-label,.custom-control-input.is-valid~.custom-control-label{color:#28a745}.was-validated .custom-control-input:valid~.custom-control-label::before,.custom-control-input.is-valid~.custom-control-label::before{border-color:#28a745}.was-validated .custom-control-input:valid:checked~.custom-control-label::before,.custom-control-input.is-valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.was-validated .custom-control-input:valid:focus~.custom-control-label::before,.custom-control-input.is-valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before,.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.was-validated .custom-file-input:valid~.custom-file-label,.custom-file-input.is-valid~.custom-file-label{border-color:#28a745}.was-validated .custom-file-input:valid:focus~.custom-file-label,.custom-file-input.is-valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:0.75rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,.9);border-radius:.25rem}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#dc3545;padding-right:calc(1.5em + 0.75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(0.375em + 0.1875rem) center;background-size:calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + 0.75rem);background-position:top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem)}.was-validated .custom-select:invalid,.custom-select.is-invalid{border-color:#dc3545;padding-right:calc(0.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px,url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem)}.was-validated .custom-select:invalid:focus,.custom-select.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated .form-check-input:invalid~.form-check-label,.form-check-input.is-invalid~.form-check-label{color:#dc3545}.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip,.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-control-input:invalid~.custom-control-label,.custom-control-input.is-invalid~.custom-control-label{color:#dc3545}.was-validated .custom-control-input:invalid~.custom-control-label::before,.custom-control-input.is-invalid~.custom-control-label::before{border-color:#dc3545}.was-validated .custom-control-input:invalid:checked~.custom-control-label::before,.custom-control-input.is-invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.was-validated .custom-control-input:invalid:focus~.custom-control-label::before,.custom-control-input.is-invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before,.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.was-validated .custom-file-input:invalid~.custom-file-label,.custom-file-input.is-invalid~.custom-file-label{border-color:#dc3545}.was-validated .custom-file-input:invalid:focus~.custom-file-label,.custom-file-input.is-invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:flex;flex-flow:row wrap;align-items:center}.form-inline .form-check{width:100%}@media(min-width: 576px){.form-inline label{display:flex;align-items:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:flex;flex:0 0 auto;flex-flow:row wrap;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group,.form-inline .custom-select{width:auto}.form-inline .form-check{display:flex;align-items:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{align-items:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media(prefers-reduced-motion: reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn:focus,.btn.focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,131,6,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#008306;border-color:#008306}.btn-primary:hover{color:#fff;background-color:#005d04;border-color:#005003}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#005d04;border-color:#005003;box-shadow:0 0 0 .2rem rgba(38,150,43,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#008306;border-color:#008306}.btn-primary:not(:disabled):not(.disabled):active,.btn-primary:not(:disabled):not(.disabled).active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#005003;border-color:#004303}.btn-primary:not(:disabled):not(.disabled):active:focus,.btn-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(38,150,43,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light:focus,.btn-light.focus{color:#212529;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled):active,.btn-light:not(:disabled):not(.disabled).active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled):active:focus,.btn-light:not(:disabled):not(.disabled).active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(216,217,219,.5)}.btn-outline-primary{color:#008306;border-color:#008306}.btn-outline-primary:hover{color:#fff;background-color:#008306;border-color:#008306}.btn-outline-primary:focus,.btn-outline-primary.focus{box-shadow:0 0 0 .2rem rgba(0,131,6,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#008306;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled):active,.btn-outline-primary:not(:disabled):not(.disabled).active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#008306;border-color:#008306}.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,131,6,.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:focus,.btn-outline-light.focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled):active,.btn-outline-light:not(:disabled):not(.disabled).active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled):active:focus,.btn-outline-light:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-link{font-weight:400;color:#008306;text-decoration:none}.btn-link:hover{color:#e57c00;text-decoration:underline}.btn-link:focus,.btn-link.focus{text-decoration:underline}.btn-link:disabled,.btn-link.disabled{color:#6c757d;pointer-events:none}.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-sm{padding:.25rem .5rem;font-size:0.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{transition:opacity .15s linear}@media(prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}@media(prefers-reduced-motion: reduce){.collapsing{transition:none}}.nav{display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:hover,.nav-link:focus{text-decoration:none}.nav-link.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:hover,.nav-tabs .nav-link:focus{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-link.active,.nav-tabs .nav-item.show .nav-link{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#008306}.nav-fill .nav-item{flex:1 1 auto;text-align:center}.nav-justified .nav-item{flex-basis:0;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-sm,.navbar .container-md,.navbar .container-lg,.navbar .container-xl{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-nav{display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;flex-grow:1;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:hover,.navbar-toggler:focus{text-decoration:none}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media(max-width: 575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-xl{padding-right:0;padding-left:0}}@media(min-width: 576px){.navbar-expand-sm{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid,.navbar-expand-sm>.container-sm,.navbar-expand-sm>.container-md,.navbar-expand-sm>.container-lg,.navbar-expand-sm>.container-xl{flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}}@media(max-width: 767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-md,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media(min-width: 768px){.navbar-expand-md{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-md,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-xl{flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}@media(max-width: 991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media(min-width: 992px){.navbar-expand-lg{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-xl{flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}}@media(max-width: 1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media(min-width: 1200px){.navbar-expand-xl{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-xl{flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}}.navbar-expand{flex-flow:row nowrap;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-sm,.navbar-expand>.container-md,.navbar-expand>.container-lg,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-sm,.navbar-expand>.container-md,.navbar-expand>.container-lg,.navbar-expand>.container-xl{flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:flex !important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:hover,.navbar-light .navbar-brand:focus{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-link:focus{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .nav-link.active{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:hover,.navbar-light .navbar-text a:focus{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:hover,.navbar-dark .navbar-brand:focus{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-link:focus{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .nav-link.active{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:hover,.navbar-dark .navbar-text a:focus{color:#fff}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:0.75rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[x-placement^=top]{padding:.4rem 0}.bs-tooltip-top .arrow,.bs-tooltip-auto[x-placement^=top] .arrow{bottom:0}.bs-tooltip-top .arrow::before,.bs-tooltip-auto[x-placement^=top] .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-right,.bs-tooltip-auto[x-placement^=right]{padding:0 .4rem}.bs-tooltip-right .arrow,.bs-tooltip-auto[x-placement^=right] .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-right .arrow::before,.bs-tooltip-auto[x-placement^=right] .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[x-placement^=bottom]{padding:.4rem 0}.bs-tooltip-bottom .arrow,.bs-tooltip-auto[x-placement^=bottom] .arrow{top:0}.bs-tooltip-bottom .arrow::before,.bs-tooltip-auto[x-placement^=bottom] .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-left,.bs-tooltip-auto[x-placement^=left]{padding:0 .4rem}.bs-tooltip-left .arrow,.bs-tooltip-auto[x-placement^=left] .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-left .arrow::before,.bs-tooltip-auto[x-placement^=left] .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.bg-primary{background-color:#008306 !important}a.bg-primary:hover,a.bg-primary:focus,button.bg-primary:hover,button.bg-primary:focus{background-color:#005003 !important}.bg-light{background-color:#f8f9fa !important}a.bg-light:hover,a.bg-light:focus,button.bg-light:hover,button.bg-light:focus{background-color:#dae0e5 !important}.bg-white{background-color:#fff !important}.bg-transparent{background-color:transparent !important}.border{border:1px solid #dee2e6 !important}.border-top{border-top:1px solid #dee2e6 !important}.border-right{border-right:1px solid #dee2e6 !important}.border-bottom{border-bottom:1px solid #dee2e6 !important}.border-left{border-left:1px solid #dee2e6 !important}.border-0{border:0 !important}.border-top-0{border-top:0 !important}.border-right-0{border-right:0 !important}.border-bottom-0{border-bottom:0 !important}.border-left-0{border-left:0 !important}.border-primary{border-color:#008306 !important}.border-light{border-color:#f8f9fa !important}.border-white{border-color:#fff !important}.rounded-sm{border-radius:.2rem !important}.rounded{border-radius:.25rem !important}.rounded-top{border-top-left-radius:.25rem !important;border-top-right-radius:.25rem !important}.rounded-right{border-top-right-radius:.25rem !important;border-bottom-right-radius:.25rem !important}.rounded-bottom{border-bottom-right-radius:.25rem !important;border-bottom-left-radius:.25rem !important}.rounded-left{border-top-left-radius:.25rem !important;border-bottom-left-radius:.25rem !important}.rounded-lg{border-radius:.3rem !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:50rem !important}.rounded-0{border-radius:0 !important}.d-none{display:none !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}@media(min-width: 576px){.d-sm-none{display:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}}@media(min-width: 768px){.d-md-none{display:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}}@media(min-width: 992px){.d-lg-none{display:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}}@media(min-width: 1200px){.d-xl-none{display:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}}@media print{.d-print-none{display:none !important}.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-fill{flex:1 1 auto !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}@media(min-width: 576px){.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}}@media(min-width: 768px){.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}}@media(min-width: 992px){.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}}@media(min-width: 1200px){.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.m-0{margin:0 !important}.mt-0,.my-0{margin-top:0 !important}.mr-0,.mx-0{margin-right:0 !important}.mb-0,.my-0{margin-bottom:0 !important}.ml-0,.mx-0{margin-left:0 !important}.m-1{margin:.25rem !important}.mt-1,.my-1{margin-top:.25rem !important}.mr-1,.mx-1{margin-right:.25rem !important}.mb-1,.my-1{margin-bottom:.25rem !important}.ml-1,.mx-1{margin-left:.25rem !important}.m-2{margin:.5rem !important}.mt-2,.my-2{margin-top:.5rem !important}.mr-2,.mx-2{margin-right:.5rem !important}.mb-2,.my-2{margin-bottom:.5rem !important}.ml-2,.mx-2{margin-left:.5rem !important}.m-3{margin:1rem !important}.mt-3,.my-3{margin-top:1rem !important}.mr-3,.mx-3{margin-right:1rem !important}.mb-3,.my-3{margin-bottom:1rem !important}.ml-3,.mx-3{margin-left:1rem !important}.m-4{margin:1.5rem !important}.mt-4,.my-4{margin-top:1.5rem !important}.mr-4,.mx-4{margin-right:1.5rem !important}.mb-4,.my-4{margin-bottom:1.5rem !important}.ml-4,.mx-4{margin-left:1.5rem !important}.m-5{margin:3rem !important}.mt-5,.my-5{margin-top:3rem !important}.mr-5,.mx-5{margin-right:3rem !important}.mb-5,.my-5{margin-bottom:3rem !important}.ml-5,.mx-5{margin-left:3rem !important}.p-0{padding:0 !important}.pt-0,.py-0{padding-top:0 !important}.pr-0,.px-0{padding-right:0 !important}.pb-0,.py-0{padding-bottom:0 !important}.pl-0,.px-0{padding-left:0 !important}.p-1{padding:.25rem !important}.pt-1,.py-1{padding-top:.25rem !important}.pr-1,.px-1{padding-right:.25rem !important}.pb-1,.py-1{padding-bottom:.25rem !important}.pl-1,.px-1{padding-left:.25rem !important}.p-2{padding:.5rem !important}.pt-2,.py-2{padding-top:.5rem !important}.pr-2,.px-2{padding-right:.5rem !important}.pb-2,.py-2{padding-bottom:.5rem !important}.pl-2,.px-2{padding-left:.5rem !important}.p-3{padding:1rem !important}.pt-3,.py-3{padding-top:1rem !important}.pr-3,.px-3{padding-right:1rem !important}.pb-3,.py-3{padding-bottom:1rem !important}.pl-3,.px-3{padding-left:1rem !important}.p-4{padding:1.5rem !important}.pt-4,.py-4{padding-top:1.5rem !important}.pr-4,.px-4{padding-right:1.5rem !important}.pb-4,.py-4{padding-bottom:1.5rem !important}.pl-4,.px-4{padding-left:1.5rem !important}.p-5{padding:3rem !important}.pt-5,.py-5{padding-top:3rem !important}.pr-5,.px-5{padding-right:3rem !important}.pb-5,.py-5{padding-bottom:3rem !important}.pl-5,.px-5{padding-left:3rem !important}.m-n1{margin:-0.25rem !important}.mt-n1,.my-n1{margin-top:-0.25rem !important}.mr-n1,.mx-n1{margin-right:-0.25rem !important}.mb-n1,.my-n1{margin-bottom:-0.25rem !important}.ml-n1,.mx-n1{margin-left:-0.25rem !important}.m-n2{margin:-0.5rem !important}.mt-n2,.my-n2{margin-top:-0.5rem !important}.mr-n2,.mx-n2{margin-right:-0.5rem !important}.mb-n2,.my-n2{margin-bottom:-0.5rem !important}.ml-n2,.mx-n2{margin-left:-0.5rem !important}.m-n3{margin:-1rem !important}.mt-n3,.my-n3{margin-top:-1rem !important}.mr-n3,.mx-n3{margin-right:-1rem !important}.mb-n3,.my-n3{margin-bottom:-1rem !important}.ml-n3,.mx-n3{margin-left:-1rem !important}.m-n4{margin:-1.5rem !important}.mt-n4,.my-n4{margin-top:-1.5rem !important}.mr-n4,.mx-n4{margin-right:-1.5rem !important}.mb-n4,.my-n4{margin-bottom:-1.5rem !important}.ml-n4,.mx-n4{margin-left:-1.5rem !important}.m-n5{margin:-3rem !important}.mt-n5,.my-n5{margin-top:-3rem !important}.mr-n5,.mx-n5{margin-right:-3rem !important}.mb-n5,.my-n5{margin-bottom:-3rem !important}.ml-n5,.mx-n5{margin-left:-3rem !important}.m-auto{margin:auto !important}.mt-auto,.my-auto{margin-top:auto !important}.mr-auto,.mx-auto{margin-right:auto !important}.mb-auto,.my-auto{margin-bottom:auto !important}.ml-auto,.mx-auto{margin-left:auto !important}@media(min-width: 576px){.m-sm-0{margin:0 !important}.mt-sm-0,.my-sm-0{margin-top:0 !important}.mr-sm-0,.mx-sm-0{margin-right:0 !important}.mb-sm-0,.my-sm-0{margin-bottom:0 !important}.ml-sm-0,.mx-sm-0{margin-left:0 !important}.m-sm-1{margin:.25rem !important}.mt-sm-1,.my-sm-1{margin-top:.25rem !important}.mr-sm-1,.mx-sm-1{margin-right:.25rem !important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem !important}.ml-sm-1,.mx-sm-1{margin-left:.25rem !important}.m-sm-2{margin:.5rem !important}.mt-sm-2,.my-sm-2{margin-top:.5rem !important}.mr-sm-2,.mx-sm-2{margin-right:.5rem !important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem !important}.ml-sm-2,.mx-sm-2{margin-left:.5rem !important}.m-sm-3{margin:1rem !important}.mt-sm-3,.my-sm-3{margin-top:1rem !important}.mr-sm-3,.mx-sm-3{margin-right:1rem !important}.mb-sm-3,.my-sm-3{margin-bottom:1rem !important}.ml-sm-3,.mx-sm-3{margin-left:1rem !important}.m-sm-4{margin:1.5rem !important}.mt-sm-4,.my-sm-4{margin-top:1.5rem !important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem !important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem !important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem !important}.m-sm-5{margin:3rem !important}.mt-sm-5,.my-sm-5{margin-top:3rem !important}.mr-sm-5,.mx-sm-5{margin-right:3rem !important}.mb-sm-5,.my-sm-5{margin-bottom:3rem !important}.ml-sm-5,.mx-sm-5{margin-left:3rem !important}.p-sm-0{padding:0 !important}.pt-sm-0,.py-sm-0{padding-top:0 !important}.pr-sm-0,.px-sm-0{padding-right:0 !important}.pb-sm-0,.py-sm-0{padding-bottom:0 !important}.pl-sm-0,.px-sm-0{padding-left:0 !important}.p-sm-1{padding:.25rem !important}.pt-sm-1,.py-sm-1{padding-top:.25rem !important}.pr-sm-1,.px-sm-1{padding-right:.25rem !important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem !important}.pl-sm-1,.px-sm-1{padding-left:.25rem !important}.p-sm-2{padding:.5rem !important}.pt-sm-2,.py-sm-2{padding-top:.5rem !important}.pr-sm-2,.px-sm-2{padding-right:.5rem !important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem !important}.pl-sm-2,.px-sm-2{padding-left:.5rem !important}.p-sm-3{padding:1rem !important}.pt-sm-3,.py-sm-3{padding-top:1rem !important}.pr-sm-3,.px-sm-3{padding-right:1rem !important}.pb-sm-3,.py-sm-3{padding-bottom:1rem !important}.pl-sm-3,.px-sm-3{padding-left:1rem !important}.p-sm-4{padding:1.5rem !important}.pt-sm-4,.py-sm-4{padding-top:1.5rem !important}.pr-sm-4,.px-sm-4{padding-right:1.5rem !important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem !important}.pl-sm-4,.px-sm-4{padding-left:1.5rem !important}.p-sm-5{padding:3rem !important}.pt-sm-5,.py-sm-5{padding-top:3rem !important}.pr-sm-5,.px-sm-5{padding-right:3rem !important}.pb-sm-5,.py-sm-5{padding-bottom:3rem !important}.pl-sm-5,.px-sm-5{padding-left:3rem !important}.m-sm-n1{margin:-0.25rem !important}.mt-sm-n1,.my-sm-n1{margin-top:-0.25rem !important}.mr-sm-n1,.mx-sm-n1{margin-right:-0.25rem !important}.mb-sm-n1,.my-sm-n1{margin-bottom:-0.25rem !important}.ml-sm-n1,.mx-sm-n1{margin-left:-0.25rem !important}.m-sm-n2{margin:-0.5rem !important}.mt-sm-n2,.my-sm-n2{margin-top:-0.5rem !important}.mr-sm-n2,.mx-sm-n2{margin-right:-0.5rem !important}.mb-sm-n2,.my-sm-n2{margin-bottom:-0.5rem !important}.ml-sm-n2,.mx-sm-n2{margin-left:-0.5rem !important}.m-sm-n3{margin:-1rem !important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem !important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem !important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem !important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem !important}.m-sm-n4{margin:-1.5rem !important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem !important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem !important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem !important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem !important}.m-sm-n5{margin:-3rem !important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem !important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem !important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem !important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem !important}.m-sm-auto{margin:auto !important}.mt-sm-auto,.my-sm-auto{margin-top:auto !important}.mr-sm-auto,.mx-sm-auto{margin-right:auto !important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto !important}.ml-sm-auto,.mx-sm-auto{margin-left:auto !important}}@media(min-width: 768px){.m-md-0{margin:0 !important}.mt-md-0,.my-md-0{margin-top:0 !important}.mr-md-0,.mx-md-0{margin-right:0 !important}.mb-md-0,.my-md-0{margin-bottom:0 !important}.ml-md-0,.mx-md-0{margin-left:0 !important}.m-md-1{margin:.25rem !important}.mt-md-1,.my-md-1{margin-top:.25rem !important}.mr-md-1,.mx-md-1{margin-right:.25rem !important}.mb-md-1,.my-md-1{margin-bottom:.25rem !important}.ml-md-1,.mx-md-1{margin-left:.25rem !important}.m-md-2{margin:.5rem !important}.mt-md-2,.my-md-2{margin-top:.5rem !important}.mr-md-2,.mx-md-2{margin-right:.5rem !important}.mb-md-2,.my-md-2{margin-bottom:.5rem !important}.ml-md-2,.mx-md-2{margin-left:.5rem !important}.m-md-3{margin:1rem !important}.mt-md-3,.my-md-3{margin-top:1rem !important}.mr-md-3,.mx-md-3{margin-right:1rem !important}.mb-md-3,.my-md-3{margin-bottom:1rem !important}.ml-md-3,.mx-md-3{margin-left:1rem !important}.m-md-4{margin:1.5rem !important}.mt-md-4,.my-md-4{margin-top:1.5rem !important}.mr-md-4,.mx-md-4{margin-right:1.5rem !important}.mb-md-4,.my-md-4{margin-bottom:1.5rem !important}.ml-md-4,.mx-md-4{margin-left:1.5rem !important}.m-md-5{margin:3rem !important}.mt-md-5,.my-md-5{margin-top:3rem !important}.mr-md-5,.mx-md-5{margin-right:3rem !important}.mb-md-5,.my-md-5{margin-bottom:3rem !important}.ml-md-5,.mx-md-5{margin-left:3rem !important}.p-md-0{padding:0 !important}.pt-md-0,.py-md-0{padding-top:0 !important}.pr-md-0,.px-md-0{padding-right:0 !important}.pb-md-0,.py-md-0{padding-bottom:0 !important}.pl-md-0,.px-md-0{padding-left:0 !important}.p-md-1{padding:.25rem !important}.pt-md-1,.py-md-1{padding-top:.25rem !important}.pr-md-1,.px-md-1{padding-right:.25rem !important}.pb-md-1,.py-md-1{padding-bottom:.25rem !important}.pl-md-1,.px-md-1{padding-left:.25rem !important}.p-md-2{padding:.5rem !important}.pt-md-2,.py-md-2{padding-top:.5rem !important}.pr-md-2,.px-md-2{padding-right:.5rem !important}.pb-md-2,.py-md-2{padding-bottom:.5rem !important}.pl-md-2,.px-md-2{padding-left:.5rem !important}.p-md-3{padding:1rem !important}.pt-md-3,.py-md-3{padding-top:1rem !important}.pr-md-3,.px-md-3{padding-right:1rem !important}.pb-md-3,.py-md-3{padding-bottom:1rem !important}.pl-md-3,.px-md-3{padding-left:1rem !important}.p-md-4{padding:1.5rem !important}.pt-md-4,.py-md-4{padding-top:1.5rem !important}.pr-md-4,.px-md-4{padding-right:1.5rem !important}.pb-md-4,.py-md-4{padding-bottom:1.5rem !important}.pl-md-4,.px-md-4{padding-left:1.5rem !important}.p-md-5{padding:3rem !important}.pt-md-5,.py-md-5{padding-top:3rem !important}.pr-md-5,.px-md-5{padding-right:3rem !important}.pb-md-5,.py-md-5{padding-bottom:3rem !important}.pl-md-5,.px-md-5{padding-left:3rem !important}.m-md-n1{margin:-0.25rem !important}.mt-md-n1,.my-md-n1{margin-top:-0.25rem !important}.mr-md-n1,.mx-md-n1{margin-right:-0.25rem !important}.mb-md-n1,.my-md-n1{margin-bottom:-0.25rem !important}.ml-md-n1,.mx-md-n1{margin-left:-0.25rem !important}.m-md-n2{margin:-0.5rem !important}.mt-md-n2,.my-md-n2{margin-top:-0.5rem !important}.mr-md-n2,.mx-md-n2{margin-right:-0.5rem !important}.mb-md-n2,.my-md-n2{margin-bottom:-0.5rem !important}.ml-md-n2,.mx-md-n2{margin-left:-0.5rem !important}.m-md-n3{margin:-1rem !important}.mt-md-n3,.my-md-n3{margin-top:-1rem !important}.mr-md-n3,.mx-md-n3{margin-right:-1rem !important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem !important}.ml-md-n3,.mx-md-n3{margin-left:-1rem !important}.m-md-n4{margin:-1.5rem !important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem !important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem !important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem !important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem !important}.m-md-n5{margin:-3rem !important}.mt-md-n5,.my-md-n5{margin-top:-3rem !important}.mr-md-n5,.mx-md-n5{margin-right:-3rem !important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem !important}.ml-md-n5,.mx-md-n5{margin-left:-3rem !important}.m-md-auto{margin:auto !important}.mt-md-auto,.my-md-auto{margin-top:auto !important}.mr-md-auto,.mx-md-auto{margin-right:auto !important}.mb-md-auto,.my-md-auto{margin-bottom:auto !important}.ml-md-auto,.mx-md-auto{margin-left:auto !important}}@media(min-width: 992px){.m-lg-0{margin:0 !important}.mt-lg-0,.my-lg-0{margin-top:0 !important}.mr-lg-0,.mx-lg-0{margin-right:0 !important}.mb-lg-0,.my-lg-0{margin-bottom:0 !important}.ml-lg-0,.mx-lg-0{margin-left:0 !important}.m-lg-1{margin:.25rem !important}.mt-lg-1,.my-lg-1{margin-top:.25rem !important}.mr-lg-1,.mx-lg-1{margin-right:.25rem !important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem !important}.ml-lg-1,.mx-lg-1{margin-left:.25rem !important}.m-lg-2{margin:.5rem !important}.mt-lg-2,.my-lg-2{margin-top:.5rem !important}.mr-lg-2,.mx-lg-2{margin-right:.5rem !important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem !important}.ml-lg-2,.mx-lg-2{margin-left:.5rem !important}.m-lg-3{margin:1rem !important}.mt-lg-3,.my-lg-3{margin-top:1rem !important}.mr-lg-3,.mx-lg-3{margin-right:1rem !important}.mb-lg-3,.my-lg-3{margin-bottom:1rem !important}.ml-lg-3,.mx-lg-3{margin-left:1rem !important}.m-lg-4{margin:1.5rem !important}.mt-lg-4,.my-lg-4{margin-top:1.5rem !important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem !important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem !important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem !important}.m-lg-5{margin:3rem !important}.mt-lg-5,.my-lg-5{margin-top:3rem !important}.mr-lg-5,.mx-lg-5{margin-right:3rem !important}.mb-lg-5,.my-lg-5{margin-bottom:3rem !important}.ml-lg-5,.mx-lg-5{margin-left:3rem !important}.p-lg-0{padding:0 !important}.pt-lg-0,.py-lg-0{padding-top:0 !important}.pr-lg-0,.px-lg-0{padding-right:0 !important}.pb-lg-0,.py-lg-0{padding-bottom:0 !important}.pl-lg-0,.px-lg-0{padding-left:0 !important}.p-lg-1{padding:.25rem !important}.pt-lg-1,.py-lg-1{padding-top:.25rem !important}.pr-lg-1,.px-lg-1{padding-right:.25rem !important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem !important}.pl-lg-1,.px-lg-1{padding-left:.25rem !important}.p-lg-2{padding:.5rem !important}.pt-lg-2,.py-lg-2{padding-top:.5rem !important}.pr-lg-2,.px-lg-2{padding-right:.5rem !important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem !important}.pl-lg-2,.px-lg-2{padding-left:.5rem !important}.p-lg-3{padding:1rem !important}.pt-lg-3,.py-lg-3{padding-top:1rem !important}.pr-lg-3,.px-lg-3{padding-right:1rem !important}.pb-lg-3,.py-lg-3{padding-bottom:1rem !important}.pl-lg-3,.px-lg-3{padding-left:1rem !important}.p-lg-4{padding:1.5rem !important}.pt-lg-4,.py-lg-4{padding-top:1.5rem !important}.pr-lg-4,.px-lg-4{padding-right:1.5rem !important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem !important}.pl-lg-4,.px-lg-4{padding-left:1.5rem !important}.p-lg-5{padding:3rem !important}.pt-lg-5,.py-lg-5{padding-top:3rem !important}.pr-lg-5,.px-lg-5{padding-right:3rem !important}.pb-lg-5,.py-lg-5{padding-bottom:3rem !important}.pl-lg-5,.px-lg-5{padding-left:3rem !important}.m-lg-n1{margin:-0.25rem !important}.mt-lg-n1,.my-lg-n1{margin-top:-0.25rem !important}.mr-lg-n1,.mx-lg-n1{margin-right:-0.25rem !important}.mb-lg-n1,.my-lg-n1{margin-bottom:-0.25rem !important}.ml-lg-n1,.mx-lg-n1{margin-left:-0.25rem !important}.m-lg-n2{margin:-0.5rem !important}.mt-lg-n2,.my-lg-n2{margin-top:-0.5rem !important}.mr-lg-n2,.mx-lg-n2{margin-right:-0.5rem !important}.mb-lg-n2,.my-lg-n2{margin-bottom:-0.5rem !important}.ml-lg-n2,.mx-lg-n2{margin-left:-0.5rem !important}.m-lg-n3{margin:-1rem !important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem !important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem !important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem !important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem !important}.m-lg-n4{margin:-1.5rem !important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem !important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem !important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem !important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem !important}.m-lg-n5{margin:-3rem !important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem !important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem !important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem !important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem !important}.m-lg-auto{margin:auto !important}.mt-lg-auto,.my-lg-auto{margin-top:auto !important}.mr-lg-auto,.mx-lg-auto{margin-right:auto !important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto !important}.ml-lg-auto,.mx-lg-auto{margin-left:auto !important}}@media(min-width: 1200px){.m-xl-0{margin:0 !important}.mt-xl-0,.my-xl-0{margin-top:0 !important}.mr-xl-0,.mx-xl-0{margin-right:0 !important}.mb-xl-0,.my-xl-0{margin-bottom:0 !important}.ml-xl-0,.mx-xl-0{margin-left:0 !important}.m-xl-1{margin:.25rem !important}.mt-xl-1,.my-xl-1{margin-top:.25rem !important}.mr-xl-1,.mx-xl-1{margin-right:.25rem !important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem !important}.ml-xl-1,.mx-xl-1{margin-left:.25rem !important}.m-xl-2{margin:.5rem !important}.mt-xl-2,.my-xl-2{margin-top:.5rem !important}.mr-xl-2,.mx-xl-2{margin-right:.5rem !important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem !important}.ml-xl-2,.mx-xl-2{margin-left:.5rem !important}.m-xl-3{margin:1rem !important}.mt-xl-3,.my-xl-3{margin-top:1rem !important}.mr-xl-3,.mx-xl-3{margin-right:1rem !important}.mb-xl-3,.my-xl-3{margin-bottom:1rem !important}.ml-xl-3,.mx-xl-3{margin-left:1rem !important}.m-xl-4{margin:1.5rem !important}.mt-xl-4,.my-xl-4{margin-top:1.5rem !important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem !important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem !important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem !important}.m-xl-5{margin:3rem !important}.mt-xl-5,.my-xl-5{margin-top:3rem !important}.mr-xl-5,.mx-xl-5{margin-right:3rem !important}.mb-xl-5,.my-xl-5{margin-bottom:3rem !important}.ml-xl-5,.mx-xl-5{margin-left:3rem !important}.p-xl-0{padding:0 !important}.pt-xl-0,.py-xl-0{padding-top:0 !important}.pr-xl-0,.px-xl-0{padding-right:0 !important}.pb-xl-0,.py-xl-0{padding-bottom:0 !important}.pl-xl-0,.px-xl-0{padding-left:0 !important}.p-xl-1{padding:.25rem !important}.pt-xl-1,.py-xl-1{padding-top:.25rem !important}.pr-xl-1,.px-xl-1{padding-right:.25rem !important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem !important}.pl-xl-1,.px-xl-1{padding-left:.25rem !important}.p-xl-2{padding:.5rem !important}.pt-xl-2,.py-xl-2{padding-top:.5rem !important}.pr-xl-2,.px-xl-2{padding-right:.5rem !important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem !important}.pl-xl-2,.px-xl-2{padding-left:.5rem !important}.p-xl-3{padding:1rem !important}.pt-xl-3,.py-xl-3{padding-top:1rem !important}.pr-xl-3,.px-xl-3{padding-right:1rem !important}.pb-xl-3,.py-xl-3{padding-bottom:1rem !important}.pl-xl-3,.px-xl-3{padding-left:1rem !important}.p-xl-4{padding:1.5rem !important}.pt-xl-4,.py-xl-4{padding-top:1.5rem !important}.pr-xl-4,.px-xl-4{padding-right:1.5rem !important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem !important}.pl-xl-4,.px-xl-4{padding-left:1.5rem !important}.p-xl-5{padding:3rem !important}.pt-xl-5,.py-xl-5{padding-top:3rem !important}.pr-xl-5,.px-xl-5{padding-right:3rem !important}.pb-xl-5,.py-xl-5{padding-bottom:3rem !important}.pl-xl-5,.px-xl-5{padding-left:3rem !important}.m-xl-n1{margin:-0.25rem !important}.mt-xl-n1,.my-xl-n1{margin-top:-0.25rem !important}.mr-xl-n1,.mx-xl-n1{margin-right:-0.25rem !important}.mb-xl-n1,.my-xl-n1{margin-bottom:-0.25rem !important}.ml-xl-n1,.mx-xl-n1{margin-left:-0.25rem !important}.m-xl-n2{margin:-0.5rem !important}.mt-xl-n2,.my-xl-n2{margin-top:-0.5rem !important}.mr-xl-n2,.mx-xl-n2{margin-right:-0.5rem !important}.mb-xl-n2,.my-xl-n2{margin-bottom:-0.5rem !important}.ml-xl-n2,.mx-xl-n2{margin-left:-0.5rem !important}.m-xl-n3{margin:-1rem !important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem !important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem !important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem !important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem !important}.m-xl-n4{margin:-1.5rem !important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem !important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem !important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem !important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem !important}.m-xl-n5{margin:-3rem !important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem !important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem !important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem !important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem !important}.m-xl-auto{margin:auto !important}.mt-xl-auto,.my-xl-auto{margin-top:auto !important}.mr-xl-auto,.mx-xl-auto{margin-right:auto !important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto !important}.ml-xl-auto,.mx-xl-auto{margin-left:auto !important}}.highlight{border-radius:.3em;background-color:#212529;color:#f8f9fa}.highlight pre{padding:.7em;color:#f8f9fa}.highlight .c1{color:#adb5bd;background-color:#212529}.highlight .k,.highlight .kc,.highlight .kn,.highlight .ow{color:#00ac07}.highlight .nb,.highlight .ne,.highlight .nf,.highlight .vm{color:#ff8c04}.highlight .s1,.highlight .s2,.highlight .sa,.highlight .se,.highlight .si,.highlight .mi{color:#ff7efd}.highlight .c1,.highlight .nf,.highlight .sa,.highlight .se,.highlight .si{font-style:italic}.highlight .k,.highlight .kn,.highlight .ow{font-weight:bold}@media(min-width: 768px){.instaloaderdoc-sidebar{padding-right:0;border-right:1px solid #dee2e6 !important}}@media(max-width: 991.98px){.instaloaderdoc-sidebar{border-bottom:1px solid #dee2e6 !important}}@media(min-width: 768px){.instaloaderdoc-sidebar>nav{height:100vh;overflow-y:auto;padding-top:.5rem}@supports((position: -webkit-sticky) or (position: sticky)){.instaloaderdoc-sidebar>nav{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}}.instaloaderdoc-sidebar>nav ul{list-style-type:none;padding-left:0}.instaloaderdoc-sidebar>nav li{padding-top:.2em;padding-bottom:.2em}.instaloaderdoc-sidebar>nav li.toctree-l2.current>ul{padding-left:1em}.instaloaderdoc-sidebar>nav a.current,.instaloaderdoc-sidebar>nav a.active,.instaloaderdoc-sidebar>nav li.current>a{color:#b26000;font-weight:500}.instaloaderdoc-sidebar>nav a.current:hover,.instaloaderdoc-sidebar>nav a.active:hover,.instaloaderdoc-sidebar>nav li.current>a:hover{color:#e57c00}.instaloaderdoc-sidebar>nav a:hover{text-decoration:none}.admonition,.topic{border-radius:.3em;border:1px solid #ced4da;background-color:#f8f9fa}ul.simple>li>p{margin-bottom:0}.nav-link{padding-top:0;padding-bottom:0}
0 !function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=2)}([function(t,e){t.exports=jQuery},function(t,e,n){
1 /*!
2 * Bootstrap util.js v4.5.0 (https://getbootstrap.com/)
3 * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 */
6 t.exports=function(t){"use strict";function e(e){var r=this,i=!1;return t(this).one(n.TRANSITION_END,(function(){i=!0})),setTimeout((function(){i||n.triggerTransitionEnd(r)}),e),this}t=t&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t;var n={TRANSITION_END:"bsTransitionEnd",getUID:function(t){do{t+=~~(1e6*Math.random())}while(document.getElementById(t));return t},getSelectorFromElement:function(t){var e=t.getAttribute("data-target");if(!e||"#"===e){var n=t.getAttribute("href");e=n&&"#"!==n?n.trim():""}try{return document.querySelector(e)?e:null}catch(t){return null}},getTransitionDurationFromElement:function(e){if(!e)return 0;var n=t(e).css("transition-duration"),r=t(e).css("transition-delay"),i=parseFloat(n),o=parseFloat(r);return i||o?(n=n.split(",")[0],r=r.split(",")[0],1e3*(parseFloat(n)+parseFloat(r))):0},reflow:function(t){return t.offsetHeight},triggerTransitionEnd:function(e){t(e).trigger("transitionend")},supportsTransitionEnd:function(){return Boolean("transitionend")},isElement:function(t){return(t[0]||t).nodeType},typeCheckConfig:function(t,e,r){for(var i in r)if(Object.prototype.hasOwnProperty.call(r,i)){var o=r[i],s=e[i],a=s&&n.isElement(s)?"element":null==(l=s)?""+l:{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(o).test(a))throw new Error(t.toUpperCase()+': Option "'+i+'" provided type "'+a+'" but expected type "'+o+'".')}var l},findShadowRoot:function(t){if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){var e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?n.findShadowRoot(t.parentNode):null},jQueryDetection:function(){if(void 0===t)throw new TypeError("Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.");var e=t.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1===e[0]&&9===e[1]&&e[2]<1||e[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}};return n.jQueryDetection(),t.fn.emulateTransitionEnd=e,t.event.special[n.TRANSITION_END]={bindType:"transitionend",delegateType:"transitionend",handle:function(e){if(t(e.target).is(this))return e.handleObj.handler.apply(this,arguments)}},n}(n(0))},function(t,e,n){n(3),t.exports=n(9)},function(t,e,n){"use strict";var r=this&&this.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(e,"__esModule",{value:!0});var i=r(n(0));n(1),n(4),n(7),n(8),i.default((function(){i.default("a.reference[title]").attr("data-toggle","tooltip"),i.default("a.headerlink[title]").attr("data-toggle","tooltip"),i.default('[data-toggle="tooltip"]').tooltip(),i.default(".instaloaderdoc-sidebar > nav > ul > li.current").attr("id","localtoc"),i.default("#localtoc ul").addClass("nav flex-column"),i.default("#localtoc ul li").addClass("nav-item"),i.default("#localtoc ul li a").addClass("nav-link"),i.default("body").scrollspy({target:"#localtoc"});var t="#"+i.default(".section:first").attr("id");i.default("#localtoc > a.current").attr("href",t)}))},function(t,e,n){
7 /*!
8 * Bootstrap tooltip.js v4.5.0 (https://getbootstrap.com/)
9 * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
10 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
11 */
12 t.exports=function(t,e,n){"use strict";function r(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}function i(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function o(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function s(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?o(Object(n),!0).forEach((function(e){i(t,e,n[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))}))}return t}t=t&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t,e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e,n=n&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n;var a=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],l={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},c=/^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/gi,f=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i;function u(t,e,n){if(0===t.length)return t;if(n&&"function"==typeof n)return n(t);for(var r=(new window.DOMParser).parseFromString(t,"text/html"),i=Object.keys(e),o=[].slice.call(r.body.querySelectorAll("*")),s=function(t,n){var r=o[t],s=r.nodeName.toLowerCase();if(-1===i.indexOf(r.nodeName.toLowerCase()))return r.parentNode.removeChild(r),"continue";var l=[].slice.call(r.attributes),u=[].concat(e["*"]||[],e[s]||[]);l.forEach((function(t){(function(t,e){var n=t.nodeName.toLowerCase();if(-1!==e.indexOf(n))return-1===a.indexOf(n)||Boolean(t.nodeValue.match(c)||t.nodeValue.match(f));for(var r=e.filter((function(t){return t instanceof RegExp})),i=0,o=r.length;i<o;i++)if(n.match(r[i]))return!0;return!1})(t,u)||r.removeAttribute(t.nodeName)}))},l=0,u=o.length;l<u;l++)s(l);return r.body.innerHTML}var h="tooltip",p=".bs.tooltip",d=t.fn[h],g=new RegExp("(^|\\s)bs-tooltip\\S+","g"),m=["sanitize","whiteList","sanitizeFn"],v={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string|function)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)",sanitize:"boolean",sanitizeFn:"(null|function)",whiteList:"object",popperConfig:"(null|object)"},b={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"},y={animation:!0,template:'<div class="tooltip" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:l,popperConfig:null},_={HIDE:"hide"+p,HIDDEN:"hidden"+p,SHOW:"show"+p,SHOWN:"shown"+p,INSERTED:"inserted"+p,CLICK:"click"+p,FOCUSIN:"focusin"+p,FOCUSOUT:"focusout"+p,MOUSEENTER:"mouseenter"+p,MOUSELEAVE:"mouseleave"+p},w=function(){function i(t,n){if(void 0===e)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(n),this.tip=null,this._setListeners()}var o,a,l,c=i.prototype;return c.enable=function(){this._isEnabled=!0},c.disable=function(){this._isEnabled=!1},c.toggleEnabled=function(){this._isEnabled=!this._isEnabled},c.toggle=function(e){if(this._isEnabled)if(e){var n=this.constructor.DATA_KEY,r=t(e.currentTarget).data(n);r||(r=new this.constructor(e.currentTarget,this._getDelegateConfig()),t(e.currentTarget).data(n,r)),r._activeTrigger.click=!r._activeTrigger.click,r._isWithActiveTrigger()?r._enter(null,r):r._leave(null,r)}else{if(t(this.getTipElement()).hasClass("show"))return void this._leave(null,this);this._enter(null,this)}},c.dispose=function(){clearTimeout(this._timeout),t.removeData(this.element,this.constructor.DATA_KEY),t(this.element).off(this.constructor.EVENT_KEY),t(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&t(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},c.show=function(){var r=this;if("none"===t(this.element).css("display"))throw new Error("Please use show on visible elements");var i=t.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){t(this.element).trigger(i);var o=n.findShadowRoot(this.element),s=t.contains(null!==o?o:this.element.ownerDocument.documentElement,this.element);if(i.isDefaultPrevented()||!s)return;var a=this.getTipElement(),l=n.getUID(this.constructor.NAME);a.setAttribute("id",l),this.element.setAttribute("aria-describedby",l),this.setContent(),this.config.animation&&t(a).addClass("fade");var c="function"==typeof this.config.placement?this.config.placement.call(this,a,this.element):this.config.placement,f=this._getAttachment(c);this.addAttachmentClass(f);var u=this._getContainer();t(a).data(this.constructor.DATA_KEY,this),t.contains(this.element.ownerDocument.documentElement,this.tip)||t(a).appendTo(u),t(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new e(this.element,a,this._getPopperConfig(f)),t(a).addClass("show"),"ontouchstart"in document.documentElement&&t(document.body).children().on("mouseover",null,t.noop);var h=function(){r.config.animation&&r._fixTransition();var e=r._hoverState;r._hoverState=null,t(r.element).trigger(r.constructor.Event.SHOWN),"out"===e&&r._leave(null,r)};if(t(this.tip).hasClass("fade")){var p=n.getTransitionDurationFromElement(this.tip);t(this.tip).one(n.TRANSITION_END,h).emulateTransitionEnd(p)}else h()}},c.hide=function(e){var r=this,i=this.getTipElement(),o=t.Event(this.constructor.Event.HIDE),s=function(){"show"!==r._hoverState&&i.parentNode&&i.parentNode.removeChild(i),r._cleanTipClass(),r.element.removeAttribute("aria-describedby"),t(r.element).trigger(r.constructor.Event.HIDDEN),null!==r._popper&&r._popper.destroy(),e&&e()};if(t(this.element).trigger(o),!o.isDefaultPrevented()){if(t(i).removeClass("show"),"ontouchstart"in document.documentElement&&t(document.body).children().off("mouseover",null,t.noop),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,t(this.tip).hasClass("fade")){var a=n.getTransitionDurationFromElement(i);t(i).one(n.TRANSITION_END,s).emulateTransitionEnd(a)}else s();this._hoverState=""}},c.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},c.isWithContent=function(){return Boolean(this.getTitle())},c.addAttachmentClass=function(e){t(this.getTipElement()).addClass("bs-tooltip-"+e)},c.getTipElement=function(){return this.tip=this.tip||t(this.config.template)[0],this.tip},c.setContent=function(){var e=this.getTipElement();this.setElementContent(t(e.querySelectorAll(".tooltip-inner")),this.getTitle()),t(e).removeClass("fade show")},c.setElementContent=function(e,n){"object"!=typeof n||!n.nodeType&&!n.jquery?this.config.html?(this.config.sanitize&&(n=u(n,this.config.whiteList,this.config.sanitizeFn)),e.html(n)):e.text(n):this.config.html?t(n).parent().is(e)||e.empty().append(n):e.text(t(n).text())},c.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},c._getPopperConfig=function(t){var e=this;return s(s({},{placement:t,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:".arrow"},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),this.config.popperConfig)},c._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=s(s({},e.offsets),t.config.offset(e.offsets,t.element)||{}),e}:e.offset=this.config.offset,e},c._getContainer=function(){return!1===this.config.container?document.body:n.isElement(this.config.container)?t(this.config.container):t(document).find(this.config.container)},c._getAttachment=function(t){return b[t.toUpperCase()]},c._setListeners=function(){var e=this;this.config.trigger.split(" ").forEach((function(n){if("click"===n)t(e.element).on(e.constructor.Event.CLICK,e.config.selector,(function(t){return e.toggle(t)}));else if("manual"!==n){var r="hover"===n?e.constructor.Event.MOUSEENTER:e.constructor.Event.FOCUSIN,i="hover"===n?e.constructor.Event.MOUSELEAVE:e.constructor.Event.FOCUSOUT;t(e.element).on(r,e.config.selector,(function(t){return e._enter(t)})).on(i,e.config.selector,(function(t){return e._leave(t)}))}})),this._hideModalHandler=function(){e.element&&e.hide()},t(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=s(s({},this.config),{},{trigger:"manual",selector:""}):this._fixTitle()},c._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},c._enter=function(e,n){var r=this.constructor.DATA_KEY;(n=n||t(e.currentTarget).data(r))||(n=new this.constructor(e.currentTarget,this._getDelegateConfig()),t(e.currentTarget).data(r,n)),e&&(n._activeTrigger["focusin"===e.type?"focus":"hover"]=!0),t(n.getTipElement()).hasClass("show")||"show"===n._hoverState?n._hoverState="show":(clearTimeout(n._timeout),n._hoverState="show",n.config.delay&&n.config.delay.show?n._timeout=setTimeout((function(){"show"===n._hoverState&&n.show()}),n.config.delay.show):n.show())},c._leave=function(e,n){var r=this.constructor.DATA_KEY;(n=n||t(e.currentTarget).data(r))||(n=new this.constructor(e.currentTarget,this._getDelegateConfig()),t(e.currentTarget).data(r,n)),e&&(n._activeTrigger["focusout"===e.type?"focus":"hover"]=!1),n._isWithActiveTrigger()||(clearTimeout(n._timeout),n._hoverState="out",n.config.delay&&n.config.delay.hide?n._timeout=setTimeout((function(){"out"===n._hoverState&&n.hide()}),n.config.delay.hide):n.hide())},c._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},c._getConfig=function(e){var r=t(this.element).data();return Object.keys(r).forEach((function(t){-1!==m.indexOf(t)&&delete r[t]})),"number"==typeof(e=s(s(s({},this.constructor.Default),r),"object"==typeof e&&e?e:{})).delay&&(e.delay={show:e.delay,hide:e.delay}),"number"==typeof e.title&&(e.title=e.title.toString()),"number"==typeof e.content&&(e.content=e.content.toString()),n.typeCheckConfig(h,e,this.constructor.DefaultType),e.sanitize&&(e.template=u(e.template,e.whiteList,e.sanitizeFn)),e},c._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},c._cleanTipClass=function(){var e=t(this.getTipElement()),n=e.attr("class").match(g);null!==n&&n.length&&e.removeClass(n.join(""))},c._handlePopperPlacementChange=function(t){this.tip=t.instance.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},c._fixTransition=function(){var e=this.getTipElement(),n=this.config.animation;null===e.getAttribute("x-placement")&&(t(e).removeClass("fade"),this.config.animation=!1,this.hide(),this.show(),this.config.animation=n)},i._jQueryInterface=function(e){return this.each((function(){var n=t(this).data("bs.tooltip"),r="object"==typeof e&&e;if((n||!/dispose|hide/.test(e))&&(n||(n=new i(this,r),t(this).data("bs.tooltip",n)),"string"==typeof e)){if(void 0===n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},o=i,l=[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return y}},{key:"NAME",get:function(){return h}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return _}},{key:"EVENT_KEY",get:function(){return p}},{key:"DefaultType",get:function(){return v}}],(a=null)&&r(o.prototype,a),l&&r(o,l),i}();return t.fn[h]=w._jQueryInterface,t.fn[h].Constructor=w,t.fn[h].noConflict=function(){return t.fn[h]=d,w._jQueryInterface},w}(n(0),n(5),n(1))},function(t,e,n){"use strict";n.r(e),function(t){
13 /**!
14 * @fileOverview Kickass library to create and place poppers near their reference elements.
15 * @version 1.16.1
16 * @license
17 * Copyright (c) 2016 Federico Zivolo and contributors
18 *
19 * Permission is hereby granted, free of charge, to any person obtaining a copy
20 * of this software and associated documentation files (the "Software"), to deal
21 * in the Software without restriction, including without limitation the rights
22 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23 * copies of the Software, and to permit persons to whom the Software is
24 * furnished to do so, subject to the following conditions:
25 *
26 * The above copyright notice and this permission notice shall be included in all
27 * copies or substantial portions of the Software.
28 *
29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 * SOFTWARE.
36 */
37 var n="undefined"!=typeof window&&"undefined"!=typeof document&&"undefined"!=typeof navigator,r=function(){for(var t=["Edge","Trident","Firefox"],e=0;e<t.length;e+=1)if(n&&navigator.userAgent.indexOf(t[e])>=0)return 1;return 0}();var i=n&&window.Promise?function(t){var e=!1;return function(){e||(e=!0,window.Promise.resolve().then((function(){e=!1,t()})))}}:function(t){var e=!1;return function(){e||(e=!0,setTimeout((function(){e=!1,t()}),r))}};function o(t){return t&&"[object Function]"==={}.toString.call(t)}function s(t,e){if(1!==t.nodeType)return[];var n=t.ownerDocument.defaultView.getComputedStyle(t,null);return e?n[e]:n}function a(t){return"HTML"===t.nodeName?t:t.parentNode||t.host}function l(t){if(!t)return document.body;switch(t.nodeName){case"HTML":case"BODY":return t.ownerDocument.body;case"#document":return t.body}var e=s(t),n=e.overflow,r=e.overflowX,i=e.overflowY;return/(auto|scroll|overlay)/.test(n+i+r)?t:l(a(t))}function c(t){return t&&t.referenceNode?t.referenceNode:t}var f=n&&!(!window.MSInputMethodContext||!document.documentMode),u=n&&/MSIE 10/.test(navigator.userAgent);function h(t){return 11===t?f:10===t?u:f||u}function p(t){if(!t)return document.documentElement;for(var e=h(10)?document.body:null,n=t.offsetParent||null;n===e&&t.nextElementSibling;)n=(t=t.nextElementSibling).offsetParent;var r=n&&n.nodeName;return r&&"BODY"!==r&&"HTML"!==r?-1!==["TH","TD","TABLE"].indexOf(n.nodeName)&&"static"===s(n,"position")?p(n):n:t?t.ownerDocument.documentElement:document.documentElement}function d(t){return null!==t.parentNode?d(t.parentNode):t}function g(t,e){if(!(t&&t.nodeType&&e&&e.nodeType))return document.documentElement;var n=t.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_FOLLOWING,r=n?t:e,i=n?e:t,o=document.createRange();o.setStart(r,0),o.setEnd(i,0);var s,a,l=o.commonAncestorContainer;if(t!==l&&e!==l||r.contains(i))return"BODY"===(a=(s=l).nodeName)||"HTML"!==a&&p(s.firstElementChild)!==s?p(l):l;var c=d(t);return c.host?g(c.host,e):g(t,d(e).host)}function m(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top",n="top"===e?"scrollTop":"scrollLeft",r=t.nodeName;if("BODY"===r||"HTML"===r){var i=t.ownerDocument.documentElement,o=t.ownerDocument.scrollingElement||i;return o[n]}return t[n]}function v(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=m(e,"top"),i=m(e,"left"),o=n?-1:1;return t.top+=r*o,t.bottom+=r*o,t.left+=i*o,t.right+=i*o,t}function b(t,e){var n="x"===e?"Left":"Top",r="Left"===n?"Right":"Bottom";return parseFloat(t["border"+n+"Width"])+parseFloat(t["border"+r+"Width"])}function y(t,e,n,r){return Math.max(e["offset"+t],e["scroll"+t],n["client"+t],n["offset"+t],n["scroll"+t],h(10)?parseInt(n["offset"+t])+parseInt(r["margin"+("Height"===t?"Top":"Left")])+parseInt(r["margin"+("Height"===t?"Bottom":"Right")]):0)}function _(t){var e=t.body,n=t.documentElement,r=h(10)&&getComputedStyle(n);return{height:y("Height",e,n,r),width:y("Width",e,n,r)}}var w=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},E=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),O=function(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t},T=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t};function C(t){return T({},t,{right:t.left+t.width,bottom:t.top+t.height})}function S(t){var e={};try{if(h(10)){e=t.getBoundingClientRect();var n=m(t,"top"),r=m(t,"left");e.top+=n,e.left+=r,e.bottom+=n,e.right+=r}else e=t.getBoundingClientRect()}catch(t){}var i={left:e.left,top:e.top,width:e.right-e.left,height:e.bottom-e.top},o="HTML"===t.nodeName?_(t.ownerDocument):{},a=o.width||t.clientWidth||i.width,l=o.height||t.clientHeight||i.height,c=t.offsetWidth-a,f=t.offsetHeight-l;if(c||f){var u=s(t);c-=b(u,"x"),f-=b(u,"y"),i.width-=c,i.height-=f}return C(i)}function j(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=h(10),i="HTML"===e.nodeName,o=S(t),a=S(e),c=l(t),f=s(e),u=parseFloat(f.borderTopWidth),p=parseFloat(f.borderLeftWidth);n&&i&&(a.top=Math.max(a.top,0),a.left=Math.max(a.left,0));var d=C({top:o.top-a.top-u,left:o.left-a.left-p,width:o.width,height:o.height});if(d.marginTop=0,d.marginLeft=0,!r&&i){var g=parseFloat(f.marginTop),m=parseFloat(f.marginLeft);d.top-=u-g,d.bottom-=u-g,d.left-=p-m,d.right-=p-m,d.marginTop=g,d.marginLeft=m}return(r&&!n?e.contains(c):e===c&&"BODY"!==c.nodeName)&&(d=v(d,e)),d}function D(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.ownerDocument.documentElement,r=j(t,n),i=Math.max(n.clientWidth,window.innerWidth||0),o=Math.max(n.clientHeight,window.innerHeight||0),s=e?0:m(n),a=e?0:m(n,"left"),l={top:s-r.top+r.marginTop,left:a-r.left+r.marginLeft,width:i,height:o};return C(l)}function x(t){var e=t.nodeName;if("BODY"===e||"HTML"===e)return!1;if("fixed"===s(t,"position"))return!0;var n=a(t);return!!n&&x(n)}function A(t){if(!t||!t.parentElement||h())return document.documentElement;for(var e=t.parentElement;e&&"none"===s(e,"transform");)e=e.parentElement;return e||document.documentElement}function P(t,e,n,r){var i=arguments.length>4&&void 0!==arguments[4]&&arguments[4],o={top:0,left:0},s=i?A(t):g(t,c(e));if("viewport"===r)o=D(s,i);else{var f=void 0;"scrollParent"===r?"BODY"===(f=l(a(e))).nodeName&&(f=t.ownerDocument.documentElement):f="window"===r?t.ownerDocument.documentElement:r;var u=j(f,s,i);if("HTML"!==f.nodeName||x(s))o=u;else{var h=_(t.ownerDocument),p=h.height,d=h.width;o.top+=u.top-u.marginTop,o.bottom=p+u.top,o.left+=u.left-u.marginLeft,o.right=d+u.left}}var m="number"==typeof(n=n||0);return o.left+=m?n:n.left||0,o.top+=m?n:n.top||0,o.right-=m?n:n.right||0,o.bottom-=m?n:n.bottom||0,o}function N(t){return t.width*t.height}function k(t,e,n,r,i){var o=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0;if(-1===t.indexOf("auto"))return t;var s=P(n,r,o,i),a={top:{width:s.width,height:e.top-s.top},right:{width:s.right-e.right,height:s.height},bottom:{width:s.width,height:s.bottom-e.bottom},left:{width:e.left-s.left,height:s.height}},l=Object.keys(a).map((function(t){return T({key:t},a[t],{area:N(a[t])})})).sort((function(t,e){return e.area-t.area})),c=l.filter((function(t){var e=t.width,r=t.height;return e>=n.clientWidth&&r>=n.clientHeight})),f=c.length>0?c[0].key:l[0].key,u=t.split("-")[1];return f+(u?"-"+u:"")}function F(t,e,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,i=r?A(e):g(e,c(n));return j(n,i,r)}function L(t){var e=t.ownerDocument.defaultView.getComputedStyle(t),n=parseFloat(e.marginTop||0)+parseFloat(e.marginBottom||0),r=parseFloat(e.marginLeft||0)+parseFloat(e.marginRight||0);return{width:t.offsetWidth+r,height:t.offsetHeight+n}}function I(t){var e={left:"right",right:"left",bottom:"top",top:"bottom"};return t.replace(/left|right|bottom|top/g,(function(t){return e[t]}))}function M(t,e,n){n=n.split("-")[0];var r=L(t),i={width:r.width,height:r.height},o=-1!==["right","left"].indexOf(n),s=o?"top":"left",a=o?"left":"top",l=o?"height":"width",c=o?"width":"height";return i[s]=e[s]+e[l]/2-r[l]/2,i[a]=n===a?e[a]-r[c]:e[I(a)],i}function H(t,e){return Array.prototype.find?t.find(e):t.filter(e)[0]}function R(t,e,n){return(void 0===n?t:t.slice(0,function(t,e,n){if(Array.prototype.findIndex)return t.findIndex((function(t){return t[e]===n}));var r=H(t,(function(t){return t[e]===n}));return t.indexOf(r)}(t,"name",n))).forEach((function(t){t.function&&console.warn("`modifier.function` is deprecated, use `modifier.fn`!");var n=t.function||t.fn;t.enabled&&o(n)&&(e.offsets.popper=C(e.offsets.popper),e.offsets.reference=C(e.offsets.reference),e=n(e,t))})),e}function B(){if(!this.state.isDestroyed){var t={instance:this,styles:{},arrowStyles:{},attributes:{},flipped:!1,offsets:{}};t.offsets.reference=F(this.state,this.popper,this.reference,this.options.positionFixed),t.placement=k(this.options.placement,t.offsets.reference,this.popper,this.reference,this.options.modifiers.flip.boundariesElement,this.options.modifiers.flip.padding),t.originalPlacement=t.placement,t.positionFixed=this.options.positionFixed,t.offsets.popper=M(this.popper,t.offsets.reference,t.placement),t.offsets.popper.position=this.options.positionFixed?"fixed":"absolute",t=R(this.modifiers,t),this.state.isCreated?this.options.onUpdate(t):(this.state.isCreated=!0,this.options.onCreate(t))}}function W(t,e){return t.some((function(t){var n=t.name;return t.enabled&&n===e}))}function q(t){for(var e=[!1,"ms","Webkit","Moz","O"],n=t.charAt(0).toUpperCase()+t.slice(1),r=0;r<e.length;r++){var i=e[r],o=i?""+i+n:t;if(void 0!==document.body.style[o])return o}return null}function U(){return this.state.isDestroyed=!0,W(this.modifiers,"applyStyle")&&(this.popper.removeAttribute("x-placement"),this.popper.style.position="",this.popper.style.top="",this.popper.style.left="",this.popper.style.right="",this.popper.style.bottom="",this.popper.style.willChange="",this.popper.style[q("transform")]=""),this.disableEventListeners(),this.options.removeOnDestroy&&this.popper.parentNode.removeChild(this.popper),this}function Y(t){var e=t.ownerDocument;return e?e.defaultView:window}function Q(t,e,n,r){n.updateBound=r,Y(t).addEventListener("resize",n.updateBound,{passive:!0});var i=l(t);return function t(e,n,r,i){var o="BODY"===e.nodeName,s=o?e.ownerDocument.defaultView:e;s.addEventListener(n,r,{passive:!0}),o||t(l(s.parentNode),n,r,i),i.push(s)}(i,"scroll",n.updateBound,n.scrollParents),n.scrollElement=i,n.eventsEnabled=!0,n}function V(){this.state.eventsEnabled||(this.state=Q(this.reference,this.options,this.state,this.scheduleUpdate))}function z(){var t,e;this.state.eventsEnabled&&(cancelAnimationFrame(this.scheduleUpdate),this.state=(t=this.reference,e=this.state,Y(t).removeEventListener("resize",e.updateBound),e.scrollParents.forEach((function(t){t.removeEventListener("scroll",e.updateBound)})),e.updateBound=null,e.scrollParents=[],e.scrollElement=null,e.eventsEnabled=!1,e))}function K(t){return""!==t&&!isNaN(parseFloat(t))&&isFinite(t)}function G(t,e){Object.keys(e).forEach((function(n){var r="";-1!==["width","height","top","right","bottom","left"].indexOf(n)&&K(e[n])&&(r="px"),t.style[n]=e[n]+r}))}var J=n&&/Firefox/i.test(navigator.userAgent);function $(t,e,n){var r=H(t,(function(t){return t.name===e})),i=!!r&&t.some((function(t){return t.name===n&&t.enabled&&t.order<r.order}));if(!i){var o="`"+e+"`",s="`"+n+"`";console.warn(s+" modifier is required by "+o+" modifier in order to work, be sure to include it before "+o+"!")}return i}var X=["auto-start","auto","auto-end","top-start","top","top-end","right-start","right","right-end","bottom-end","bottom","bottom-start","left-end","left","left-start"],Z=X.slice(3);function tt(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=Z.indexOf(t),r=Z.slice(n+1).concat(Z.slice(0,n));return e?r.reverse():r}var et="flip",nt="clockwise",rt="counterclockwise";function it(t,e,n,r){var i=[0,0],o=-1!==["right","left"].indexOf(r),s=t.split(/(\+|\-)/).map((function(t){return t.trim()})),a=s.indexOf(H(s,(function(t){return-1!==t.search(/,|\s/)})));s[a]&&-1===s[a].indexOf(",")&&console.warn("Offsets separated by white space(s) are deprecated, use a comma (,) instead.");var l=/\s*,\s*|\s+/,c=-1!==a?[s.slice(0,a).concat([s[a].split(l)[0]]),[s[a].split(l)[1]].concat(s.slice(a+1))]:[s];return(c=c.map((function(t,r){var i=(1===r?!o:o)?"height":"width",s=!1;return t.reduce((function(t,e){return""===t[t.length-1]&&-1!==["+","-"].indexOf(e)?(t[t.length-1]=e,s=!0,t):s?(t[t.length-1]+=e,s=!1,t):t.concat(e)}),[]).map((function(t){return function(t,e,n,r){var i=t.match(/((?:\-|\+)?\d*\.?\d*)(.*)/),o=+i[1],s=i[2];if(!o)return t;if(0===s.indexOf("%")){var a=void 0;switch(s){case"%p":a=n;break;case"%":case"%r":default:a=r}return C(a)[e]/100*o}if("vh"===s||"vw"===s){return("vh"===s?Math.max(document.documentElement.clientHeight,window.innerHeight||0):Math.max(document.documentElement.clientWidth,window.innerWidth||0))/100*o}return o}(t,i,e,n)}))}))).forEach((function(t,e){t.forEach((function(n,r){K(n)&&(i[e]+=n*("-"===t[r-1]?-1:1))}))})),i}var ot={placement:"bottom",positionFixed:!1,eventsEnabled:!0,removeOnDestroy:!1,onCreate:function(){},onUpdate:function(){},modifiers:{shift:{order:100,enabled:!0,fn:function(t){var e=t.placement,n=e.split("-")[0],r=e.split("-")[1];if(r){var i=t.offsets,o=i.reference,s=i.popper,a=-1!==["bottom","top"].indexOf(n),l=a?"left":"top",c=a?"width":"height",f={start:O({},l,o[l]),end:O({},l,o[l]+o[c]-s[c])};t.offsets.popper=T({},s,f[r])}return t}},offset:{order:200,enabled:!0,fn:function(t,e){var n=e.offset,r=t.placement,i=t.offsets,o=i.popper,s=i.reference,a=r.split("-")[0],l=void 0;return l=K(+n)?[+n,0]:it(n,o,s,a),"left"===a?(o.top+=l[0],o.left-=l[1]):"right"===a?(o.top+=l[0],o.left+=l[1]):"top"===a?(o.left+=l[0],o.top-=l[1]):"bottom"===a&&(o.left+=l[0],o.top+=l[1]),t.popper=o,t},offset:0},preventOverflow:{order:300,enabled:!0,fn:function(t,e){var n=e.boundariesElement||p(t.instance.popper);t.instance.reference===n&&(n=p(n));var r=q("transform"),i=t.instance.popper.style,o=i.top,s=i.left,a=i[r];i.top="",i.left="",i[r]="";var l=P(t.instance.popper,t.instance.reference,e.padding,n,t.positionFixed);i.top=o,i.left=s,i[r]=a,e.boundaries=l;var c=e.priority,f=t.offsets.popper,u={primary:function(t){var n=f[t];return f[t]<l[t]&&!e.escapeWithReference&&(n=Math.max(f[t],l[t])),O({},t,n)},secondary:function(t){var n="right"===t?"left":"top",r=f[n];return f[t]>l[t]&&!e.escapeWithReference&&(r=Math.min(f[n],l[t]-("right"===t?f.width:f.height))),O({},n,r)}};return c.forEach((function(t){var e=-1!==["left","top"].indexOf(t)?"primary":"secondary";f=T({},f,u[e](t))})),t.offsets.popper=f,t},priority:["left","right","top","bottom"],padding:5,boundariesElement:"scrollParent"},keepTogether:{order:400,enabled:!0,fn:function(t){var e=t.offsets,n=e.popper,r=e.reference,i=t.placement.split("-")[0],o=Math.floor,s=-1!==["top","bottom"].indexOf(i),a=s?"right":"bottom",l=s?"left":"top",c=s?"width":"height";return n[a]<o(r[l])&&(t.offsets.popper[l]=o(r[l])-n[c]),n[l]>o(r[a])&&(t.offsets.popper[l]=o(r[a])),t}},arrow:{order:500,enabled:!0,fn:function(t,e){var n;if(!$(t.instance.modifiers,"arrow","keepTogether"))return t;var r=e.element;if("string"==typeof r){if(!(r=t.instance.popper.querySelector(r)))return t}else if(!t.instance.popper.contains(r))return console.warn("WARNING: `arrow.element` must be child of its popper element!"),t;var i=t.placement.split("-")[0],o=t.offsets,a=o.popper,l=o.reference,c=-1!==["left","right"].indexOf(i),f=c?"height":"width",u=c?"Top":"Left",h=u.toLowerCase(),p=c?"left":"top",d=c?"bottom":"right",g=L(r)[f];l[d]-g<a[h]&&(t.offsets.popper[h]-=a[h]-(l[d]-g)),l[h]+g>a[d]&&(t.offsets.popper[h]+=l[h]+g-a[d]),t.offsets.popper=C(t.offsets.popper);var m=l[h]+l[f]/2-g/2,v=s(t.instance.popper),b=parseFloat(v["margin"+u]),y=parseFloat(v["border"+u+"Width"]),_=m-t.offsets.popper[h]-b-y;return _=Math.max(Math.min(a[f]-g,_),0),t.arrowElement=r,t.offsets.arrow=(O(n={},h,Math.round(_)),O(n,p,""),n),t},element:"[x-arrow]"},flip:{order:600,enabled:!0,fn:function(t,e){if(W(t.instance.modifiers,"inner"))return t;if(t.flipped&&t.placement===t.originalPlacement)return t;var n=P(t.instance.popper,t.instance.reference,e.padding,e.boundariesElement,t.positionFixed),r=t.placement.split("-")[0],i=I(r),o=t.placement.split("-")[1]||"",s=[];switch(e.behavior){case et:s=[r,i];break;case nt:s=tt(r);break;case rt:s=tt(r,!0);break;default:s=e.behavior}return s.forEach((function(a,l){if(r!==a||s.length===l+1)return t;r=t.placement.split("-")[0],i=I(r);var c=t.offsets.popper,f=t.offsets.reference,u=Math.floor,h="left"===r&&u(c.right)>u(f.left)||"right"===r&&u(c.left)<u(f.right)||"top"===r&&u(c.bottom)>u(f.top)||"bottom"===r&&u(c.top)<u(f.bottom),p=u(c.left)<u(n.left),d=u(c.right)>u(n.right),g=u(c.top)<u(n.top),m=u(c.bottom)>u(n.bottom),v="left"===r&&p||"right"===r&&d||"top"===r&&g||"bottom"===r&&m,b=-1!==["top","bottom"].indexOf(r),y=!!e.flipVariations&&(b&&"start"===o&&p||b&&"end"===o&&d||!b&&"start"===o&&g||!b&&"end"===o&&m),_=!!e.flipVariationsByContent&&(b&&"start"===o&&d||b&&"end"===o&&p||!b&&"start"===o&&m||!b&&"end"===o&&g),w=y||_;(h||v||w)&&(t.flipped=!0,(h||v)&&(r=s[l+1]),w&&(o=function(t){return"end"===t?"start":"start"===t?"end":t}(o)),t.placement=r+(o?"-"+o:""),t.offsets.popper=T({},t.offsets.popper,M(t.instance.popper,t.offsets.reference,t.placement)),t=R(t.instance.modifiers,t,"flip"))})),t},behavior:"flip",padding:5,boundariesElement:"viewport",flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(t){var e=t.placement,n=e.split("-")[0],r=t.offsets,i=r.popper,o=r.reference,s=-1!==["left","right"].indexOf(n),a=-1===["top","left"].indexOf(n);return i[s?"left":"top"]=o[n]-(a?i[s?"width":"height"]:0),t.placement=I(e),t.offsets.popper=C(i),t}},hide:{order:800,enabled:!0,fn:function(t){if(!$(t.instance.modifiers,"hide","preventOverflow"))return t;var e=t.offsets.reference,n=H(t.instance.modifiers,(function(t){return"preventOverflow"===t.name})).boundaries;if(e.bottom<n.top||e.left>n.right||e.top>n.bottom||e.right<n.left){if(!0===t.hide)return t;t.hide=!0,t.attributes["x-out-of-boundaries"]=""}else{if(!1===t.hide)return t;t.hide=!1,t.attributes["x-out-of-boundaries"]=!1}return t}},computeStyle:{order:850,enabled:!0,fn:function(t,e){var n=e.x,r=e.y,i=t.offsets.popper,o=H(t.instance.modifiers,(function(t){return"applyStyle"===t.name})).gpuAcceleration;void 0!==o&&console.warn("WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!");var s=void 0!==o?o:e.gpuAcceleration,a=p(t.instance.popper),l=S(a),c={position:i.position},f=function(t,e){var n=t.offsets,r=n.popper,i=n.reference,o=Math.round,s=Math.floor,a=function(t){return t},l=o(i.width),c=o(r.width),f=-1!==["left","right"].indexOf(t.placement),u=-1!==t.placement.indexOf("-"),h=e?f||u||l%2==c%2?o:s:a,p=e?o:a;return{left:h(l%2==1&&c%2==1&&!u&&e?r.left-1:r.left),top:p(r.top),bottom:p(r.bottom),right:h(r.right)}}(t,window.devicePixelRatio<2||!J),u="bottom"===n?"top":"bottom",h="right"===r?"left":"right",d=q("transform"),g=void 0,m=void 0;if(m="bottom"===u?"HTML"===a.nodeName?-a.clientHeight+f.bottom:-l.height+f.bottom:f.top,g="right"===h?"HTML"===a.nodeName?-a.clientWidth+f.right:-l.width+f.right:f.left,s&&d)c[d]="translate3d("+g+"px, "+m+"px, 0)",c[u]=0,c[h]=0,c.willChange="transform";else{var v="bottom"===u?-1:1,b="right"===h?-1:1;c[u]=m*v,c[h]=g*b,c.willChange=u+", "+h}var y={"x-placement":t.placement};return t.attributes=T({},y,t.attributes),t.styles=T({},c,t.styles),t.arrowStyles=T({},t.offsets.arrow,t.arrowStyles),t},gpuAcceleration:!0,x:"bottom",y:"right"},applyStyle:{order:900,enabled:!0,fn:function(t){var e,n;return G(t.instance.popper,t.styles),e=t.instance.popper,n=t.attributes,Object.keys(n).forEach((function(t){!1!==n[t]?e.setAttribute(t,n[t]):e.removeAttribute(t)})),t.arrowElement&&Object.keys(t.arrowStyles).length&&G(t.arrowElement,t.arrowStyles),t},onLoad:function(t,e,n,r,i){var o=F(i,e,t,n.positionFixed),s=k(n.placement,o,e,t,n.modifiers.flip.boundariesElement,n.modifiers.flip.padding);return e.setAttribute("x-placement",s),G(e,{position:n.positionFixed?"fixed":"absolute"}),n},gpuAcceleration:void 0}}},st=function(){function t(e,n){var r=this,s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};w(this,t),this.scheduleUpdate=function(){return requestAnimationFrame(r.update)},this.update=i(this.update.bind(this)),this.options=T({},t.Defaults,s),this.state={isDestroyed:!1,isCreated:!1,scrollParents:[]},this.reference=e&&e.jquery?e[0]:e,this.popper=n&&n.jquery?n[0]:n,this.options.modifiers={},Object.keys(T({},t.Defaults.modifiers,s.modifiers)).forEach((function(e){r.options.modifiers[e]=T({},t.Defaults.modifiers[e]||{},s.modifiers?s.modifiers[e]:{})})),this.modifiers=Object.keys(this.options.modifiers).map((function(t){return T({name:t},r.options.modifiers[t])})).sort((function(t,e){return t.order-e.order})),this.modifiers.forEach((function(t){t.enabled&&o(t.onLoad)&&t.onLoad(r.reference,r.popper,r.options,t,r.state)})),this.update();var a=this.options.eventsEnabled;a&&this.enableEventListeners(),this.state.eventsEnabled=a}return E(t,[{key:"update",value:function(){return B.call(this)}},{key:"destroy",value:function(){return U.call(this)}},{key:"enableEventListeners",value:function(){return V.call(this)}},{key:"disableEventListeners",value:function(){return z.call(this)}}]),t}();st.Utils=("undefined"!=typeof window?window:t).PopperUtils,st.placements=X,st.Defaults=ot,e.default=st}.call(this,n(6))},function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){
38 /*!
39 * Bootstrap scrollspy.js v4.5.0 (https://getbootstrap.com/)
40 * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
41 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
42 */
43 t.exports=function(t,e){"use strict";function n(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function i(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function o(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?i(Object(n),!0).forEach((function(e){r(t,e,n[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))}))}return t}t=t&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t,e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e;var s="scrollspy",a=t.fn[s],l={offset:10,method:"auto",target:""},c={offset:"number",method:"string",target:"(string|element)"},f=function(){function r(e,n){var r=this;this._element=e,this._scrollElement="BODY"===e.tagName?window:e,this._config=this._getConfig(n),this._selector=this._config.target+" .nav-link,"+this._config.target+" .list-group-item,"+this._config.target+" .dropdown-item",this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,t(this._scrollElement).on("scroll.bs.scrollspy",(function(t){return r._process(t)})),this.refresh(),this._process()}var i,a,f,u=r.prototype;return u.refresh=function(){var n=this,r=this._scrollElement===this._scrollElement.window?"offset":"position",i="auto"===this._config.method?r:this._config.method,o="position"===i?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),[].slice.call(document.querySelectorAll(this._selector)).map((function(n){var r,s=e.getSelectorFromElement(n);if(s&&(r=document.querySelector(s)),r){var a=r.getBoundingClientRect();if(a.width||a.height)return[t(r)[i]().top+o,s]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(t){n._offsets.push(t[0]),n._targets.push(t[1])}))},u.dispose=function(){t.removeData(this._element,"bs.scrollspy"),t(this._scrollElement).off(".bs.scrollspy"),this._element=null,this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},u._getConfig=function(n){if("string"!=typeof(n=o(o({},l),"object"==typeof n&&n?n:{})).target&&e.isElement(n.target)){var r=t(n.target).attr("id");r||(r=e.getUID(s),t(n.target).attr("id",r)),n.target="#"+r}return e.typeCheckConfig(s,n,c),n},u._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},u._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},u._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},u._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var r=this._targets[this._targets.length-1];this._activeTarget!==r&&this._activate(r)}else{if(this._activeTarget&&t<this._offsets[0]&&this._offsets[0]>0)return this._activeTarget=null,void this._clear();for(var i=this._offsets.length;i--;)this._activeTarget!==this._targets[i]&&t>=this._offsets[i]&&(void 0===this._offsets[i+1]||t<this._offsets[i+1])&&this._activate(this._targets[i])}},u._activate=function(e){this._activeTarget=e,this._clear();var n=this._selector.split(",").map((function(t){return t+'[data-target="'+e+'"],'+t+'[href="'+e+'"]'})),r=t([].slice.call(document.querySelectorAll(n.join(","))));r.hasClass("dropdown-item")?(r.closest(".dropdown").find(".dropdown-toggle").addClass("active"),r.addClass("active")):(r.addClass("active"),r.parents(".nav, .list-group").prev(".nav-link, .list-group-item").addClass("active"),r.parents(".nav, .list-group").prev(".nav-item").children(".nav-link").addClass("active")),t(this._scrollElement).trigger("activate.bs.scrollspy",{relatedTarget:e})},u._clear=function(){[].slice.call(document.querySelectorAll(this._selector)).filter((function(t){return t.classList.contains("active")})).forEach((function(t){return t.classList.remove("active")}))},r._jQueryInterface=function(e){return this.each((function(){var n=t(this).data("bs.scrollspy");if(n||(n=new r(this,"object"==typeof e&&e),t(this).data("bs.scrollspy",n)),"string"==typeof e){if(void 0===n[e])throw new TypeError('No method named "'+e+'"');n[e]()}}))},i=r,f=[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return l}}],(a=null)&&n(i.prototype,a),f&&n(i,f),r}();return t(window).on("load.bs.scrollspy.data-api",(function(){for(var e=[].slice.call(document.querySelectorAll('[data-spy="scroll"]')),n=e.length;n--;){var r=t(e[n]);f._jQueryInterface.call(r,r.data())}})),t.fn[s]=f._jQueryInterface,t.fn[s].Constructor=f,t.fn[s].noConflict=function(){return t.fn[s]=a,f._jQueryInterface},f}(n(0),n(1))},function(t,e,n){
44 /*!
45 * Bootstrap collapse.js v4.5.0 (https://getbootstrap.com/)
46 * Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
47 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
48 */
49 t.exports=function(t,e){"use strict";function n(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function i(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function o(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?i(Object(n),!0).forEach((function(e){r(t,e,n[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e))}))}return t}t=t&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t,e=e&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e;var s="collapse",a="bs.collapse",l=t.fn[s],c={toggle:!0,parent:""},f={toggle:"boolean",parent:"(string|element)"},u=function(){function r(t,n){this._isTransitioning=!1,this._element=t,this._config=this._getConfig(n),this._triggerArray=[].slice.call(document.querySelectorAll('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'));for(var r=[].slice.call(document.querySelectorAll('[data-toggle="collapse"]')),i=0,o=r.length;i<o;i++){var s=r[i],a=e.getSelectorFromElement(s),l=[].slice.call(document.querySelectorAll(a)).filter((function(e){return e===t}));null!==a&&l.length>0&&(this._selector=a,this._triggerArray.push(s))}this._parent=this._config.parent?this._getParent():null,this._config.parent||this._addAriaAndCollapsedClass(this._element,this._triggerArray),this._config.toggle&&this.toggle()}var i,l,u,h=r.prototype;return h.toggle=function(){t(this._element).hasClass("show")?this.hide():this.show()},h.show=function(){var n,i,o=this;if(!(this._isTransitioning||t(this._element).hasClass("show")||(this._parent&&0===(n=[].slice.call(this._parent.querySelectorAll(".show, .collapsing")).filter((function(t){return"string"==typeof o._config.parent?t.getAttribute("data-parent")===o._config.parent:t.classList.contains("collapse")}))).length&&(n=null),n&&(i=t(n).not(this._selector).data(a))&&i._isTransitioning))){var s=t.Event("show.bs.collapse");if(t(this._element).trigger(s),!s.isDefaultPrevented()){n&&(r._jQueryInterface.call(t(n).not(this._selector),"hide"),i||t(n).data(a,null));var l=this._getDimension();t(this._element).removeClass("collapse").addClass("collapsing"),this._element.style[l]=0,this._triggerArray.length&&t(this._triggerArray).removeClass("collapsed").attr("aria-expanded",!0),this.setTransitioning(!0);var c="scroll"+(l[0].toUpperCase()+l.slice(1)),f=e.getTransitionDurationFromElement(this._element);t(this._element).one(e.TRANSITION_END,(function(){t(o._element).removeClass("collapsing").addClass("collapse show"),o._element.style[l]="",o.setTransitioning(!1),t(o._element).trigger("shown.bs.collapse")})).emulateTransitionEnd(f),this._element.style[l]=this._element[c]+"px"}}},h.hide=function(){var n=this;if(!this._isTransitioning&&t(this._element).hasClass("show")){var r=t.Event("hide.bs.collapse");if(t(this._element).trigger(r),!r.isDefaultPrevented()){var i=this._getDimension();this._element.style[i]=this._element.getBoundingClientRect()[i]+"px",e.reflow(this._element),t(this._element).addClass("collapsing").removeClass("collapse show");var o=this._triggerArray.length;if(o>0)for(var s=0;s<o;s++){var a=this._triggerArray[s],l=e.getSelectorFromElement(a);null!==l&&(t([].slice.call(document.querySelectorAll(l))).hasClass("show")||t(a).addClass("collapsed").attr("aria-expanded",!1))}this.setTransitioning(!0),this._element.style[i]="";var c=e.getTransitionDurationFromElement(this._element);t(this._element).one(e.TRANSITION_END,(function(){n.setTransitioning(!1),t(n._element).removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")})).emulateTransitionEnd(c)}}},h.setTransitioning=function(t){this._isTransitioning=t},h.dispose=function(){t.removeData(this._element,a),this._config=null,this._parent=null,this._element=null,this._triggerArray=null,this._isTransitioning=null},h._getConfig=function(t){return(t=o(o({},c),t)).toggle=Boolean(t.toggle),e.typeCheckConfig(s,t,f),t},h._getDimension=function(){return t(this._element).hasClass("width")?"width":"height"},h._getParent=function(){var n,i=this;e.isElement(this._config.parent)?(n=this._config.parent,void 0!==this._config.parent.jquery&&(n=this._config.parent[0])):n=document.querySelector(this._config.parent);var o='[data-toggle="collapse"][data-parent="'+this._config.parent+'"]',s=[].slice.call(n.querySelectorAll(o));return t(s).each((function(t,e){i._addAriaAndCollapsedClass(r._getTargetFromElement(e),[e])})),n},h._addAriaAndCollapsedClass=function(e,n){var r=t(e).hasClass("show");n.length&&t(n).toggleClass("collapsed",!r).attr("aria-expanded",r)},r._getTargetFromElement=function(t){var n=e.getSelectorFromElement(t);return n?document.querySelector(n):null},r._jQueryInterface=function(e){return this.each((function(){var n=t(this),i=n.data(a),s=o(o(o({},c),n.data()),"object"==typeof e&&e?e:{});if(!i&&s.toggle&&"string"==typeof e&&/show|hide/.test(e)&&(s.toggle=!1),i||(i=new r(this,s),n.data(a,i)),"string"==typeof e){if(void 0===i[e])throw new TypeError('No method named "'+e+'"');i[e]()}}))},i=r,u=[{key:"VERSION",get:function(){return"4.5.0"}},{key:"Default",get:function(){return c}}],(l=null)&&n(i.prototype,l),u&&n(i,u),r}();return t(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',(function(n){"A"===n.currentTarget.tagName&&n.preventDefault();var r=t(this),i=e.getSelectorFromElement(this),o=[].slice.call(document.querySelectorAll(i));t(o).each((function(){var e=t(this),n=e.data(a)?"toggle":r.data();u._jQueryInterface.call(e,n)}))})),t.fn[s]=u._jQueryInterface,t.fn[s].Constructor=u,t.fn[s].noConflict=function(){return t.fn[s]=l,u._jQueryInterface},u}(n(0),n(1))},function(t,e,n){}]);
00 {% extends "!layout.html" %}
1
21 {% set html5_doctype = True %}
3
4 {% set script_files = script_files + ['_static/bootstrap-4.1.3.bundle.min.js', '_static/instaloader.js'] %}
5
2 {% set script_files = script_files + ['_static/instaloaderdoc.js'] %}
63 {% block htmltitle %}
74 {% if pagename == "index" %}
85 <title>{{ title|striptags|e }}</title>
107 <title>{{ title|striptags|e }}{{ titlesuffix }}</title>
118 {% endif %}
129 {% endblock %}
13
1410 {% block extrahead %}
1511 {{ super() }}
1612 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
2117 <link rel="canonical" href="https://instaloader.github.io/{{ pagename }}.html"/>
2218 {% endif %}
2319 {% endblock %}
24
2520 {% block header %}
26 <nav class="navbar navbar-expand-sm navbar-light bg-light fixed-top border-bottom">
21 <nav class="navbar navbar-light navbar-expand bg-light border-bottom">
2722 <a class="navbar-brand" href="{{ pathto(master_doc) }}">
2823 <img src="{{ pathto('_static/' + logo, 1) }}" width="30" height="30" class="d-inline-block align-top" alt="logo">
29 Instaloader
24 <span class="ml-3">Instaloader</span>
3025 </a>
3126 <ul class="navbar-nav mr-auto">
32 <li class="nav-item ml-0 ml-sm-2 ml-md-0">
33 <a target="_blank" class="nav-link"
27 <li class="nav-item ml-0 ml-sm-2">
28 <a class="nav-link"
3429 href="https://github.com/instaloader/instaloader/releases/tag/v{{ current_release }}"
35 title="Released on {{ current_release_date }}" data-toggle="tooltip">v<b>{{ current_release }}</b></a>
30 title="Released on {{ current_release_date }}" data-toggle="tooltip">
31 v<b>{{ current_release }}</b>
32 </a>
3633 </li>
3734 </ul>
38 <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarLinks"
39 aria-controls="navbarLinks" aria-expanded="false" aria-label="Toggle navigation">
35 <ul class="navbar-nav ml-auto d-none d-sm-flex">
36 <li class="nav-item">
37 <a class="nav-link" href="https://github.com/instaloader/instaloader/issues">
38 Issues
39 </a>
40 </li>
41 <li class="nav-item">
42 <a class="nav-link" href="https://github.com/instaloader/instaloader/releases">
43 Releases
44 </a>
45 </li>
46 <li class="nav-item">
47 <a class="nav-link" href="https://github.com/instaloader/instaloader">
48 GitHub
49 </a>
50 </li>
51 </ul>
52 <button class="d-inline-block d-md-none btn btn-outline-primary btn-sm" type="button"
53 data-toggle="collapse" data-target="#instaloaderdocSidebar" aria-controls="instaloaderdocSidebar"
54 aria-expanded="false" aria-label="Toggle navigation">
4055 <span class="navbar-toggler-icon"></span>
4156 </button>
42 <div class="collapse navbar-collapse" id="navbarLinks">
43 <ul class="navbar-nav ml-auto">
44 <li class="nav-item">
45 <a target="_blank" class="nav-link" href="https://github.com/instaloader/instaloader/issues">Issues</a>
46 </li>
47 <li class="nav-item">
48 <a target="_blank" class="nav-link" href="https://github.com/instaloader/instaloader/releases">Releases</a>
49 </li>
50 <li class="nav-item">
51 <a target="_blank" class="nav-link" href="https://github.com/instaloader/instaloader">GitHub</a>
52 </li>
53 </ul>
54 <form class="form-inline" action="search.html" method="get">
55 <div class="input-group my-2 my-sm-0 ml-2">
56 <input class="form-control" type="search" placeholder="Search" aria-label="Search" name="q">
57 <div class="input-group-append">
58 <button class="btn btn-success btn-small" type="submit">Go</button>
59 </div>
60 </div>
61 </form>
62 </div>
63 {% if pagename != "index" %}
64 <button type="button" class="btn btn-success d-md-none btn-small ml-2" data-toggle="modal"
65 data-target="#navbarToc">
66 TOC
67 </button>
68 {% endif %}
6957 </nav>
70 {% if pagename != "index" %}
71 <div class="modal fade" id="navbarToc" tabindex="-1" role="dialog"
72 aria-hidden="true" aria-labelledby="navbarTocTitle">
73 <div class="modal-dialog modal-dialog-centered" role="document">
74 <div class="modal-content">
75 <div class="modal-header">
76 <h5 class="modal-title" id="navbarTocTitle">Contents</h5>
77 <button type="button" class="close" data-dismiss="modal" aria-label="Close">
78 <span aria-hidden="true">&times;</span>
79 </button>
80 </div>
81 <div class="modal-body">
82 {{ toctree(maxdepth=-1) }}
83 </div>
84 </div>
85 </div>
86 </div>
87 {% endif %}
8858 {% endblock %}
89
9059 {% block relbar1 %}{% endblock %}
9160 {% block relbar2 %}{% endblock %}
9261 {% block footer %}{% endblock %}
9362 {% block content %}
94 <div class="container-fluid row">
95 <div class="col-12 {% if pagename != "index" %}col-md-9 col-xl-10{% endif %} doc-content">
96 {% block body %}{% endblock %}
63 <div class="container-fluid">
64 <div class="row">
65 <div class="instaloaderdoc-sidebar collapse d-md-block col-md-3 col-xl-2 bg-light"
66 id="instaloaderdocSidebar">
67 <nav role="navigation" aria-label="Table of Contents">
68 <form action="{{ pathto('search') }}" method="get" role="search" class="border-bottom mr-2 pb-2 mb-2 px-1">
69 <label class="sr-only" for="searchQueryInput">Search</label>
70 <input type="search" name="q" id="searchQueryInput" class="form-control my-2"
71 placeholder="Search..." aria-label="Search">
72 </form>
73 <h4>Contents</h4>
74 {{ toctree(maxdepth=-1) }}
75 </nav>
76 </div>
77 <main class="col-12 col-md-9 col-xl-10 pt-2" role="main">
78 {% block body %}{% endblock %}
79 </main>
9780 </div>
98 {% if pagename != "index" %}
99 <div class="d-none col-md-3 col-xl-2 bg-light doc-sidebar d-md-flex flex-column border-left">
100
101 <h3>{{ _('Table of Contents') }}</h3>
102 {{ toctree(maxdepth=-1) }}
103
104 <div class="d-flex justify-content-between small mt-auto mb-2">
105 <a class="reference internal{% if pagename == "genindex" %} current{% endif %}" href="genindex.html">Index</a>
106 {% if pagename != "genindex" and pagename != "search" %}
107 <a class="reference external"
108 href="https://github.com/instaloader/instaloader/edit/master/docs/{{ pagename }}.rst">Edit this page</a>
109 {% endif %}
110 </div>
111 </div>
112 {% endif %}
11381 </div>
114 {% endblock %}
82 {% endblock %}
1111
1212 .. highlight:: python
1313
14 .. contents::
15 :backlinks: none
16
1714 Instaloader exposes its internally used methods and structures as a Python
18 module, making it a **powerful and intuitive Python API for Instagram**,
15 module, making it a powerful and intuitive Python API for Instagram,
1916 allowing to further customize obtaining media and metadata.
2017
2118 Start with getting an instance of :class:`Instaloader`::
8481 - :meth:`Profile.get_followers`
8582 Profiles that follow given user.
8683
87 - :attr:`Post.owner_profile`, :attr:`Story.owner_profile` and :attr:`StoryItem.owner_profile`
84 - :attr:`Post.owner_profile`, :attr:`Story.owner_profile`, :attr:`StoryItem.owner_profile`
8885 Owner profile of particular object.
8986
9087 - :meth:`Post.get_likes`
9188 Profiles that liked a given :class:`Post`
9289
93 - :attr:`PostComment.owner` attribute for comment in :meth:`Post.get_comments`
90 - :attr:`PostComment.owner`
9491 Profile of a Post comment.
9592
96 A reference of the many methods provided by the :mod:`instaloader` module is
97 provided in the remainder of this document.
93 For a list of a few code examples that use the Instaloader module, see
94 :ref:`codesnippets`.
9895
99 For a list of real code examples using the Instaloader module for advanced
100 tasks, see :ref:`codesnippets`.
96 The reference of the classes and functions provided by the :mod:`instaloader` module is
97 divided into the following subsections:
10198
102 ``Instaloader`` (Main Class)
103 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
99 .. toctree::
100 :maxdepth: 2
104101
105 .. autoclass:: Instaloader
106 :no-show-inheritance:
107
108 Instagram Structures
109 ^^^^^^^^^^^^^^^^^^^^
110
111 Posts
112 """""
113
114 .. autoclass:: Post
115 :no-show-inheritance:
116
117 Additionally, the following trivial structures are defined:
118
119 .. autoclass:: PostSidecarNode
120 :no-show-inheritance:
121
122 .. autoclass:: PostComment
123 :no-show-inheritance:
124
125 .. autoclass:: PostCommentAnswer
126 :no-show-inheritance:
127
128 .. autoclass:: PostLocation
129 :no-show-inheritance:
130
131 User Stories
132 """"""""""""
133
134 .. autoclass:: Story
135 :no-show-inheritance:
136
137 .. autoclass:: StoryItem
138 :no-show-inheritance:
139
140 Highlights
141 """"""""""
142
143 .. autoclass:: Highlight
144 :no-show-inheritance:
145 :inherited-members:
146
147 Bases: :class:`Story`
148
149 .. versionadded:: 4.1
150
151 Profiles
152 """"""""
153
154 .. autoclass:: Profile
155 :no-show-inheritance:
156
157 Hashtags
158 """"""""
159
160 .. autoclass:: Hashtag
161 :no-show-inheritance:
162
163 .. versionadded:: 4.4
164
165 TopSearchResults
166 """"""""""""""""
167
168 .. autoclass:: TopSearchResults
169 :no-show-inheritance:
170
171 .. versionadded:: 4.3
172
173 Loading and Saving
174 """"""""""""""""""
175
176 :class:`Post`, :class:`StoryItem`, :class:`Profile` and :class:`Hashtag` can be saved and loaded
177 to/from JSON files.
178
179 .. autofunction:: load_structure_from_file
180
181 .. autofunction:: save_structure_to_file
182
183 Exceptions
184 ^^^^^^^^^^
185
186 .. currentmodule:: instaloader.exceptions
187
188 .. autoexception:: InstaloaderException
189 :no-show-inheritance:
190
191 .. autoexception:: ConnectionException
192
193 .. currentmodule:: instaloader
194
195 .. autoexception:: QueryReturnedBadRequestException
196
197 .. autoexception:: QueryReturnedForbiddenException
198
199 .. autoexception:: ProfileNotExistsException
200
201 .. autoexception:: ProfileHasNoPicsException
202
203 .. autoexception:: PrivateProfileNotFollowedException
204
205 .. autoexception:: LoginRequiredException
206
207 .. autoexception:: TwoFactorAuthRequiredException
208
209 .. versionadded:: 4.2
210
211 .. autoexception:: InvalidArgumentException
212
213 .. autoexception:: BadResponseException
214
215 .. autoexception:: BadCredentialsException
216
217 .. autoexception:: PostChangedException
218
219 .. autoexception:: QueryReturnedNotFoundException
220
221 .. versionchanged:: 4.3
222 QueryReturnedNotFoundException now inherits ConnectionException
223 to retry on 404 errors.
224
225
226 .. autoexception:: TooManyRequestsException
227
228 ``InstaloaderContext`` (Low-level functions)
229 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
230
231 .. autoclass:: InstaloaderContext
232 :no-show-inheritance:
102 module/instaloader
103 module/structures
104 module/nodeiterator
105 module/instaloadercontext
106 module/exceptions
3838 If :option:`--fast-update` is given, Instaloader stops when arriving at the
3939 first already-downloaded picture.
4040
41 Alternatively, you can use :option:`--latest-stamps` to have Instaloader store
42 the time each profile was last downloaded and only download newer media:
43
44 ::
45
46 instaloader --latest-stamps -- profile [profile ...]
47
48 With this option it's possible to move or delete downloaded media and still keep
49 the archive updated.
50
4151 When updating profiles, Instaloader
4252 automatically **detects profile name changes** and renames the target directory
4353 accordingly.
7686 instructs Instaloader to also **download the user's stories**,
7787
7888 - :option:`--highlights`
79 to **download highlights of each profile that is downloaded**,
89 to **download the highlights of that profile**,
8090
8191 - :option:`--tagged`
8292 to **download posts where the user is tagged**, and
8595 to **download IGTV videos**.
8696
8797 - ``"#hashtag"``
88 Posts with a certain **hashtag** (the quotes are usually necessary),
98 Posts with a certain **hashtag** (the quotes are usually necessary).
8999
90100 - ``%location id``
91101 Posts tagged with a given location; the location ID is the numerical ID
97107
98108 - ``:stories``
99109 The currently-visible **stories** of your followees (requires
100 :option:`--login`),
110 :option:`--login`).
101111
102112 - ``:feed``
103 Your **feed** (requires :option:`--login`),
113 Your **feed** (requires :option:`--login`).
104114
105115 - ``:saved``
106 Posts which are marked as **saved** (requires :option:`--login`),
116 Posts which are marked as **saved** (requires :option:`--login`).
107117
108118 - ``@profile``
109119 All profiles that are followed by ``profile``, i.e. the *followees* of
110120 ``profile`` (requires :option:`--login`).
111121
112122 - ``-post``
113 Replace **post** with the post's shortcode to download single post. Must be preceeded by ``--`` in
123 Replace **post** with the post's shortcode to download single post. Must be preceded by ``--`` in
114124 the argument list to not be mistaken as an option flag::
115125
116126 instaloader -- -B_K4CykAOtf
148158 pattern, the token ``{target}`` is replaced by the target name, and
149159 ``{profile}`` is replaced by the owner of the post which is downloaded.
150160
151 :option:`--filename-pattern` configures the path of the post's files relative
161 :option:`--filename-pattern` configures the path of the post and story's files relative
152162 to the target directory that is specified with :option:`--dirname-pattern`.
153163 The default is ``--filename-pattern={date_utc}_UTC``.
154164 The tokens ``{target}`` and ``{profile}`` are replaced like in the
155 dirname pattern. The following tokens are defined for usage with
156 :option:`--filename-pattern`:
165 dirname pattern.
166
167 :option:`--title-pattern` is similar to :option:`--filename-pattern`, but for profile
168 pics, hashtag profile pics, and highlight covers. The default is
169 ``{date_utc}_UTC_{typename}`` if :option:`--dirname-pattern` contains ``{target}`` or
170 ``{profile}``, or ``{target}_{date_utc}_UTC_{typename}`` if it does not. Some tokens
171 are not supported for this option, see below for details.
172
173 The following tokens are defined for usage with
174 :option:`--filename-pattern` and :option:`--title-pattern`:
157175
158176 - ``{target}``
159177 Target name (as given in Instaloader command line)
160178
161179 - ``{profile}`` (same as ``{owner_username}``)
162 Owner of the Post / StoryItem.
180 Owner of the Post / StoryItem / ProfilePic. For hashtag profile pics and
181 highlight covers, equivalent to ``{target}``.
163182
164183 - ``{owner_id}``
165 Unique integer ID of owner profile.
184 Unique integer ID of owner profile. For hashtag profile pics, equivalent to
185 ``{target}``.
166186
167187 - ``{shortcode}``
168 Shortcode (identifier string).
188 Shortcode (identifier string). Not available for :option:`--title-pattern`.
169189
170190 - ``{mediaid}``
171 Integer representation of shortcode.
191 Integer representation of shortcode. Not available for :option:`--title-pattern`.
192
193 - ``{filename}``
194 Instagram's internal filename.
172195
173196 - ``{date_utc}`` (same as ``{date}``)
174197 Creation time in UTC timezone.
178201
179202 {date_utc:%Y-%m-%d_%H-%M-%S}
180203
204 - ``{typename}``
205 Type of media being saved, such as GraphImage, GraphStoryVideo, profile_pic,
206 etc.
207
181208 For example, encode the poster's profile name in the filenames with::
182209
183210 instaloader --filename-pattern={date_utc}_UTC_{profile} "#hashtag"
195222 .. py:currentmodule:: instaloader
196223
197224 The options :option:`--post-filter` and :option:`--storyitem-filter`
198 allows to specify criteria that posts or story items have to
225 allow to specify criteria that posts or story items have to
199226 meet to be downloaded. If not given, all posts are downloaded.
200227
201228 The filter string must be a
207234 :option:`--post-filter` and :option:`--storyitem-filter`:
208235
209236 - :attr:`~Post.owner_username` (str), :attr:`~Post.owner_id` (int)
210 Owner profile username / userid.
237 Owner profile username / user ID.
211238
212239 - :attr:`~Post.date_utc` (datetime), :attr:`~Post.date_local` (datetime)
213240 Creation timestamp. Since :class:`~datetime.datetime` objects can be created
216243 instaloader --post-filter="date_utc <= datetime(2018, 5, 31)" target
217244
218245 - :attr:`~Post.is_video` (bool)
219 Post/StoryItem is a video. For example, you may skip videos::
246 Whether Post/StoryItem is a video. For example, you may skip videos::
220247
221248 instaloader --post-filter="not is_video" target
222249
233260 instaloader --login=your_username --post-filter=viewer_has_liked :feed
234261
235262 - :attr:`~Post.likes` (int), :attr:`~Post.comments` (int)
236 Likes count / Comments count. You might only want to download posts that
237 either you liked or were liked by many others**::
263 Likes count / comments count. You might only want to download posts that
264 were either liked by yourself or by many others::
238265
239266 instaloader --login=your_username --post-filter="likes>100 or viewer_has_liked" profile
240267
264291 You can customize what metadata to save for each Post or StoryItem with
265292 :option:`--post-metadata-txt` and :option:`--storyitem-metadata-txt`. The
266293 default is ``--post-metadata-txt={caption}`` and no storyitem metadata txt.
267 These strings are formatted similar as in the :ref:`filename-specification` and
294 These strings are formatted similar as the path patterns described in :ref:`filename-specification` and
268295 the result is saved in text files, unless it is empty.
269296
270297 Specifying these options multiple times results in output having multiple lines,
298325
299326 instaloader --login=your_username
300327
301 Then use the same parameter in your cronjob to load the session and download
328 Then use the same username in your cronjob to load the session and download
302329 the given targets::
303330
304 instaloader --login=your_username --quiet <target> [...]
331 instaloader --login=your_username --quiet target [...]
305332
306333 Instaloader saves the session file to
307334 ``~/.config/instaloader/session-YOUR-USERNAME``. See
316343 powerful and intuitive Python API for Instagram, allowing to further customize
317344 obtaining media and metadata.
318345
319 Also see :ref:`codesnippets`, where we collect example scripts that use
320 Instaloader to achieve more complex tasks.
346 Also see :ref:`codesnippets`, where we collect a few example scripts that use
347 Instaloader for simple tasks that cannot be done with the command line
348 interface.
3535 Re-Download the given object
3636
3737 - ``+args.txt``
38 Read targets (and options) from given textfile. See :option:`+args.txt`.
38 Read targets (and options) from given text file. See :option:`+args.txt`.
3939
4040 What to Download of each Post
4141 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5858
5959 .. option:: --geotags, -G
6060
61 **Download geotags** when available. Geotags are stored as a text file with
61 Download geotags when available. Geotags are stored as a text file with
6262 the location's name and a Google Maps link. This requires an additional
6363 request to the Instagram server for each picture. Requires :option:`--login`.
6464
8181 Template to write in txt file for each StoryItem. See
8282 :ref:`metadata-text-files`.
8383
84 .. option:: --slide
85
86 Download only selected images of a sidecar. You can select single images using their
87 index in the sidecar starting with the leftmost or you can specify a range of images
88 with the following syntax: ``start_index-end_index``. Example:
89 ``--slide 1`` will select only the first image, ``--slide last`` only the last one and ``--slide 1-3`` will select only
90 the first three images.
91
92 .. versionadded:: 4.6
93
8494 .. option:: --no-metadata-json
8595
8696 Do not create a JSON file containing the metadata of each post.
8898 .. option:: --no-compress-json
8999
90100 Do not xz compress JSON files, rather create pretty formatted JSONs.
91
92101
93102 What to Download of each Profile
94103 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
95104
96 .. option:: --profile-pic-only, -P
97
98 .. deprecated:: 4.1
99 Use :option:`--no-posts`.
100
101 Only download profile picture.
102
103105 .. option:: --no-posts
104106
105107 Do not download regular posts.
112114
113115 .. option:: --stories, -s
114116
115 Also **download stories** of each profile that is downloaded. Requires
117 Also download stories of each profile that is downloaded. Requires
116118 :option:`--login`.
117119
118120 .. option:: --highlights
119121
120 Also **download highlights** of each profile that is downloaded. Requires
122 Also download highlights of each profile that is downloaded. Requires
121123 :option:`--login`.
122124
123125 .. versionadded:: 4.1
133135 Also download IGTV videos.
134136
135137 .. versionadded:: 4.3
136
137 .. option:: --stories-only
138
139 .. deprecated:: 4.1
140 Use :option:`--stories` :option:`--no-posts`.
141
142 Rather than downloading regular posts of each specified profile, only
143 download stories. Requires :option:`--login`. Does not imply
144 :option:`--no-profile-pic`.
145
146 .. note::
147
148 If possible, use ``:stories`` target rather than :option:`--stories-only`
149 with all your followees. ``:stories`` uses fewer API requests.
150138
151139 Which Posts to Download
152140 ^^^^^^^^^^^^^^^^^^^^^^^
156144 For each target, stop when encountering the first already-downloaded picture.
157145 This flag is recommended when you use Instaloader to update your personal
158146 Instagram archive.
147
148 .. option:: --latest-stamps [STAMPSFILE]
149
150 Works similarly to :option:`--fast-update`, but instead of relying on already
151 downloaded media, the time each profile was downloaded is stored, and only
152 media newer than the last download is fetched. This allows updating your
153 personal Instagram archive while emptying the target directories.
154
155 Only works for media associated with a specific profile, and that is returned
156 in chronological order: profile posts, profile stories, profile IGTV posts
157 and profile tagged posts.
158
159 By default, the information is stored in
160 ``~/.config/instaloader/latest-stamps.ini``, but you can specify an
161 alternative location.
162
163 .. versionadded:: 4.8
159164
160165 .. option:: --post-filter filter, --only-if filter
161166
174179
175180 .. option:: --count COUNT, -c
176181
177 Do not attempt to download more than COUNT posts. Applies only to
178 ``#hashtag``, ``%location id``, and ``:feed``.
182 Do not attempt to download more than COUNT posts. Applies to
183 ``#hashtag``, ``%location_id``, ``:feed``, and ``:saved``.
179184
180185
181186 Login (Download Private Profiles)
182187 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
183188
184 Instaloader can **login to Instagram**. This allows downloading private
189 Instaloader can login to Instagram. This allows downloading private
185190 profiles. To login, pass the :option:`--login` option. Your session cookie (not your
186191 password!) will be saved to a local file to be reused next time you want
187192 Instaloader to login.
216221
217222 .. option:: --filename-pattern FILENAME_PATTERN
218223
219 Prefix of filenames, relative to the directory given with
224 Prefix of filenames for posts and stories, relative to the directory given with
220225 :option:`--dirname-pattern`. ``{profile}`` is replaced by the profile name,
221226 ``{target}`` is replaced by the target you specified, i.e. either ``:feed``,
222227 ``#hashtag`` or the profile name. Defaults to ``{date_utc}_UTC``.
223228 See :ref:`filename-specification` for a list of supported tokens.
224229
230 .. option:: --title-pattern TITLE_PATTERN
231
232 Prefix of filenames for profile pics, hashtag profile pics, and highlight
233 covers, relative to the directory given with :option:`--dirname-pattern`.
234 Defaults to ``{date_utc}_UTC_{typename}`` if :option:`--dirname-pattern`
235 contains ``{target}`` or ``{profile}``, otherwise defaults to
236 ``{target}_{date_utc}_UTC_{typename}``.
237 See :ref:`filename-specification` for a list of supported tokens.
238
239 .. versionadded:: 4.8
240
241 .. option:: --resume-prefix prefix
242
243 For many targets, Instaloader is capable of resuming a previously-aborted
244 download loop. To do so, it creates a JSON file within the target directory
245 when interrupted. This option controls the prefix for filenames that are
246 used to save the information to resume an interrupted download. The default
247 prefix is ``iterator``.
248
249 Resuming an interrupted download is supported for the following targets:
250 - Profile posts,
251 - Profile IGTV posts (:option:`--igtv`),
252 - Profile tagged posts (:option:`--tagged`),
253 - Saved posts (``:saved``).
254
255 This feature is enabled by default for targets where it is supported;
256 :option:`--resume-prefix` only changes the name of the iterator files.
257
258 To turn this feature off, use :option:`--no-resume`.
259
260 JSON files with resume information are always compressed, regardless of
261 :option:`--no-compress-json`.
262
263 .. versionadded:: 4.5
264
265 .. option:: --no-resume
266
267 Do not resume a previously-aborted download iteration, and do not save such
268 information when interrupted.
269
270 .. versionadded:: 4.5
271
225272 .. option:: --user-agent USER_AGENT
226273
227274 User Agent to use for HTTP requests. Per default, Instaloader pretends being
228 Chrome/51.
275 Chrome/92 on Linux.
229276
230277 .. option:: --max-connection-attempts N
231278
233280 to ``3``. If a connection fails, it can be manually skipped by hitting
234281 :kbd:`Control-c`. Set this to ``0`` to retry infinitely.
235282
236 .. option:: --commit-mode
237
238 Tries to ensure downloaded images avoid corruption in case of unexpected
239 interruption. If the last picture is corrupted, Instaloader will fix the
240 picture the next time it is run.
241
242 .. versionadded:: 4.2
243
244 .. warning::
245 We discourage from using the "commit mode" due to its bugs when being used
246 with other command line options (e.g. :issue:`257` with
247 :option:`--fast-update` and :issue:`483` with :option:`--tagged`).
248
249283 .. option:: --request-timeout N
250284
251 Seconds to wait before timing out a connection request.
285 Seconds to wait before timing out a connection request. Defaults to 300.
252286
253287 .. versionadded:: 4.3
288
289 .. versionchanged:: 4.6
290 Enabled this option by default with a timeout of 300 seconds.
291
292 .. option:: --abort-on STATUS_CODE_LIST
293
294 Comma-separated list of HTTP status codes that cause Instaloader to abort,
295 bypassing all retry logic.
296
297 For example, with ``--abort-on=302,400,429``, Instaloader will stop if a
298 request is responded with a 302 redirect, a Bad Request error, or a Too Many
299 Requests error.
300
301 .. versionadded:: 4.7
302
303 .. option:: --no-iphone
304
305 Do not attempt to download iPhone version of images and videos.
306
307 .. versionadded:: 4.8
254308
255309 Miscellaneous Options
256310 ^^^^^^^^^^^^^^^^^^^^^
265319
266320 Read arguments from file `args.txt`, a shortcut to provide arguments from
267321 file rather than command-line. This provides a convenient way to hide login
268 info from CLI, and can also be used to simplify managment of long arguments.
322 info from CLI, and can also be used to simplify management of long arguments.
269323
270324 .. note::
271325
272326 Text file should separate arguments with line breaks.
273327
274 args.txt example::
275
276 --login=MYUSERNAME
277 --password=MYPASSWORD
278 --fast-update
279 profile1
280 profile2
281
282 .. versionadded:: 4.1
328 args.txt example::
329
330 --login=MYUSERNAME
331 --password=MYPASSWORD
332 --fast-update
333 profile1
334 profile2
335
336 .. versionadded:: 4.1
+0
-20
docs/codesnippets/110_pil_captions.py less more
0 from io import BytesIO
1
2 from requests import get
3 from PIL import Image, ImageDraw
4 from instaloader import *
5
6 L = Instaloader()
7
8 # Load Post instance
9 post = load_structure_from_file(L.context, '2017-10-01_18-53-03_UTC.json.xz')
10 # or post = Post.from_shortcode(L.context, SHORTCODE)
11
12 # Render caption
13 image = Image.open(BytesIO(get(post.url).content))
14 draw = ImageDraw.Draw(image)
15 color = 'rgb(0, 0, 0)' # black color
16 draw.text((300,100), post.caption.encode('latin1', errors='ignore'), fill=color)
17
18 # Save image
19 image.save('test.jpg')
11
22 L = instaloader.Instaloader()
33
4 USER = 'your_account'
4 USER = "your_account"
55 PROFILE = USER
66
7 # Your preferred way of logging in:
7 # Load session previously saved with `instaloader -l USERNAME`:
88 L.load_session_from_file(USER)
99
1010 profile = instaloader.Profile.from_username(L.context, PROFILE)
1111
1212 likes = set()
13 print('Fetching likes of all posts of profile {}.'.format(profile.username))
13 print("Fetching likes of all posts of profile {}.".format(profile.username))
1414 for post in profile.get_posts():
1515 print(post)
1616 likes = likes | set(post.get_likes())
1717
18 print('Fetching followers of profile {}.'.format(profile.username))
18 print("Fetching followers of profile {}.".format(profile.username))
1919 followers = set(profile.get_followers())
2020
2121 ghosts = followers - likes
2222
23 print('Storing ghosts into file.')
24 with open('/YOUR PATH/inactive-users.txt', 'w') as f:
23 print("Storing ghosts into file.")
24 with open("inactive-users.txt", 'w') as f:
2525 for ghost in ghosts:
2626 print(ghost.username, file=f)
2222
2323 def import_session(cookiefile, sessionfile):
2424 print("Using cookies from {}.".format(cookiefile))
25 conn = connect(cookiefile)
25 conn = connect(f"file:{cookiefile}?immutable=1", uri=True)
2626 try:
2727 cookie_data = conn.execute(
2828 "SELECT name, value FROM moz_cookies WHERE baseDomain='instagram.com'"
88 UNTIL = datetime(2020, 5, 11) # closer to today, not inclusive
99
1010 k = 0 # initiate k
11 k_list = [] # uncomment this to tune k
11 #k_list = [] # uncomment this to tune k
1212
1313 for post in posts:
1414 postdate = post.date
2323 continue
2424 else:
2525 L.download_post(post, "#urbanphotography")
26 k = 0 # set k to 0
2726 # if you want to tune k, uncomment below to get your k max
2827 #k_list.append(k)
28 k = 0 # set k to 0
29
2930 #max(k_list)
4141 :func:`~itertools.takewhile` makes the assumption that the post iterator returns
4242 posts in exact chronological order. As discussed in :issue:`666`, the following
4343 approach fits for an **almost chronological order**, where up to *k* older posts
44 are inserted into an otherwise chronological order, such as an Hashtag feed.
44 are inserted into an otherwise chronological order, such as a Hashtag feed.
4545
4646 .. literalinclude:: codesnippets/666_historical_hashtag_data.py
4747
4949 ------------------------------------
5050
5151 To obtain a list of your inactive followers, i.e. followers that did not like
52 any of your pictures, into a file you can use this approach.
52 any of your pictures, you can use this approach.
5353
5454 .. literalinclude:: codesnippets/120_ghost_followers.py
5555
7777 Only one Post per User
7878 ----------------------
7979
80 To download only the one most recent post from each user, this snippet creates a
81 :class:`set` that contains the users of which a post has already been
82 downloaded. While iterating the posts, it checks whether the post's owner
83 already is in the set. If not, the post is downloaded from Instagram and the
84 user is added to that set.
80 To download only the single most recent post per user within a hashtag feed,
81 this snippet uses a :class:`set` that contains the users of whom a post has
82 already been downloaded. For each post, it checks whether the post's creator is
83 already contained in that set. If not, the post is downloaded from Instagram and
84 the user is added to that set.
8585
8686 .. literalinclude:: codesnippets/113_only_one_per_user.py
8787
9393 Top X Posts of User
9494 -------------------
9595
96 With Instaloader, it is easy to download the few most-liked pictres of a user.
96 With Instaloader, it is easy to download the few most-liked pictures of a user.
9797
9898 .. literalinclude:: codesnippets/194_top_x_of_user.py
9999
100100 Discussed in :issue:`194`.
101
102 Upgrade Images by Local Copies
103 ------------------------------
104
105 The following script finds local versions of images fetched by Instaloader, in
106 order to upgrade the downloaded images by locally-found versions with better
107 quality. It uses image hashing to identify similar images.
108
109 `updgrade-instaloader-images.py <https://gist.github.com/pavelkryukov/15f93d19a99428a284a8bcec27e0187b>`__ (external link to GitHub Gist)
110
111 Discussed in :issue:`46`.
112
113 Add Captions to Images
114 ----------------------
115
116 Instaloader does not modify the downloaded JPEG file. However, one could combine
117 it with an imaging library such as Pillow or PIL to render the caption on
118 Instagram pictures. The following shows an approach.
119
120 .. literalinclude:: codesnippets/110_pil_captions.py
121
122 See also :attr:`Post.caption`, :attr:`Post.url`, :meth:`Post.from_shortcode`,
123 :func:`load_structure_from_file`.
124
125 Discussed in :issue:`110`.
126101
127102 Metadata JSON Files
128103 -------------------
4949 intersphinx_mapping = {'python': ('https://docs.python.org/3', None),
5050 'requests': ('https://requests.kennethreitz.org/en/master/', None)}
5151
52 nitpick_ignore = [('py:class', 'typing.Tuple')]
53
5254 current_release = subprocess.check_output(["git", "describe", "--abbrev=0"]).decode("ascii")[1:-1]
5355 date_format = "%e %b %Y" if platform.system() != "Windows" else "%d %b %Y"
5456 current_release_date = subprocess.check_output(
6264 'Issue #'
6365 ),
6466 'example': (
65 'https://raw.githubusercontent.com/instaloader/instaloader/v' + current_release + '/docs/codesnippets/%s',
67 'https://raw.githubusercontent.com/instaloader/instaloader/master/docs/codesnippets/%s',
6668 'Example '
6769 ),
6870 }
371373
372374 def setup(app):
373375 typing.TYPE_CHECKING = True
374 app.add_stylesheet("instaloader.css")
376 app.add_stylesheet("instaloaderdoc.css")
375377 app.connect('autodoc-process-signature', sphinx_autodoc_typehints.process_signature)
376378 app.connect('autodoc-process-docstring', sphinx_autodoc_typehints.process_docstring)
99 Instaloader's development is organized on
1010 `GitHub <https://github.com/instaloader/instaloader>`__, where Issues and Pull
1111 Requests are discussed.
12
13 Contributing to an open source project is an unmatchable opportunity to improve
14 and manifest programming skills. For issues that are good starting points to get
15 involved in Instaloader development, as they do not require deep insight into
16 Instaloader's code base, have a look at our
17 `Issues labelled 'good first issue' <https://github.com/instaloader/instaloader/contribute>`__.
18
19 This document covers several ways of how you can contribute back to Instaloader.
20
21 Answering Questions
22 -------------------
23
24 The easiest way to help out is to answer questions. If you are interested in
25 answering questions regarding Instaloader, good places to begin are
26
27 - `Questions tagged 'instaloader' on Stack Overflow <https://stackoverflow.com/questions/tagged/instaloader>`__,
28 - `Instaloader Issues labeled 'question' <https://github.com/instaloader/instaloader/issues?q=is%3Aissue+is%3Aopen+label%3Aquestion>`__.
1229
1330 Reporting Bugs
1431 --------------
3148
3249 - Include all **error messages and tracebacks** in the report.
3350
34 - If not obvious, describe **which behavior you expected**
51 - Even if it seems obvious, describe **which behavior you expected**
3552 instead of what actually happened.
3653
3754 - If we have closed an issue apparently inadvertently or inappropriately, please
4057 Writing Code or Improving the Documentation
4158 -------------------------------------------
4259
43 Changes of the Instaloader source can be proposed as a
44 `Pull Request <https://github.com/instaloader/instaloader/pulls>`__. There are only
45 few things to consider:
60 Improvements of the Instaloader source or its documentation can be proposed as a
61 `Pull Request <https://github.com/instaloader/instaloader/pulls>`__.
4662
47 - Base your Pull Request on the ``master`` branch if it fixes a bug,
48 or the ``upcoming/v4.X`` branch (if it exists at the moment of submitting the PR)
49 otherwise.
63 - Please base your Pull Request on
5064
51 - We use `Pylint <https://www.pylint.org/>`__ for error and syntax checking of
52 the source and `MyPy <https://github.com/python/mypy>`__ for type checking.
53 Beware that sometimes it might be better to disable a warning rather than
54 adapting the code to a tool's desires.
65 - ``master``, which will be released with the next minor release, if it is
5566
56 - The documentation source is located in the ``docs`` folder. The file
57 ``cli-options.rst`` is merely an RST-formatted copy of ``instaloader --help``
58 output, of which the source is in ``instaloader/__main__.py``.
67 - a bug fix that does not require extensive testing,
68 - an improvement to the documentation,
69
70 - ``upcoming/v4.X``, if it is
71
72 - a new feature,
73 - a bug fix that does require thorough testing before being released to a
74 final version.
75
76 - All Pull Requests are analyzed by `Pylint <https://www.pylint.org/>`__ for
77 error and syntax checking of the source and
78 `Mypy <https://github.com/python/mypy>`__ for type checking. You can run them
79 locally with::
80
81 pylint instaloader
82 mypy -m instaloader
83
84 - Improvements to the documentation are very welcome. The documentation is
85 created with `Sphinx <https://www.sphinx-doc.org/en/2.0/>`__, version 2,
86 and can be build locally using::
87
88 make -C docs html
89
90 - Feel free to create an issue to make sure someone from the Instaloader team
91 agrees that the change might be an improvement, or if you want to discuss
92 your basic proposal, before working on a pull request.
5993
6094 Proposing Features
6195 ------------------
97131 be implemented and the underlying problem could be solved. Also **describe
98132 alternatives** that you have considered.
99133
100 Donations
101 ---------
134 Sponsoring
135 ----------
102136
103 .. donations-start
104
105 It is a pleasure for us to share our Instaloader to the world, and we are proud
106 to have attracted such an active and motivating community, with so many users
107 who share their suggestions and ideas with us. Buying a community-sponsored beer
108 or coffee from time to time is very likely to further raise our passion for the
109 development of Instaloader.
110
111 | For donations, we provide a PayPal.Me link and a Bitcoin address.
112 | `PayPal.me/aandergr <https://www.paypal.me/aandergr>`__
113 | BTC: 1Nst4LoadeYzrKjJ1DX9CpbLXBYE9RKLwY
114
115 .. donations-end
116
117 .. (Discussion in :issue:`130`)
137 .. include:: sponsors.rst
138 :start-after: donations-start
139 :end-before: donations-end
3939 - allows **fine-grained customization** of filters and where to store
4040 downloaded media,
4141
42 - automatically **resumes previously-interrupted** download iterations,
43
4244 - is free `open source <https://github.com/instaloader/instaloader>`__
4345 software written in Python.
4446
7577 - `Issue Tracker / Bug Tracker <https://github.com/instaloader/instaloader/issues>`__
7678 - `Version History <https://github.com/instaloader/instaloader/releases>`__
7779
80 Contributing
81 ------------
82
83 As an open source project, Instaloader heavily depends on the contributions from
84 its community. See :ref:`contributing` for how you may help Instaloader to
85 become an even greater tool.
86
87 Supporters
88 ----------
89
90 .. include:: sponsors.rst
91 :start-after: donations-start
92 :end-before: donations-end
93
7894 Disclaimer
7995 ----------
8096
8298 :start-after: disclaimer-start
8399 :end-before: disclaimer-end
84100
85 Contributing
86 ------------
87
88 As an open source project, Instaloader heavily depends on the contributions from
89 its community. See :ref:`contributing` for how you may help Instaloader to
90 become an even greater tool.
91
92 .. include:: contributing.rst
93 :start-after: donations-start
94 :end-before: donations-end
95
96101 ..
97102 * :ref:`genindex`
98103 * :ref:`modindex`
44
55 .. highlight:: none
66
7 **To install Instaloader**,
7 To **install Instaloader**,
88
99 #. Ensure that you have `Python <https://www.python.org/>`__, at least
10 version 3.5 and `pip <https://pypi.python.org/pypi/pip>`__
11 installed
10 version 3.6, and `pip <https://pypi.python.org/pypi/pip>`__
11 installed.
1212
1313 #. Then, install Instaloader using::
1414
1515 pip3 install instaloader
1616
17 **To upgrade Instaloader**, do::
17 To **upgrade Instaloader** to its current version, do::
1818
1919 pip3 install --upgrade instaloader
2020
2121
22 **Alternative methods for installing Instaloader:**
22 **Alternative methods** for installing Instaloader:
2323
2424 - If you do not want to use pip, even though it is highly recommended,
2525 and prefer to **install Instaloader manually**,
2626 `Download the Source <https://github.com/instaloader/instaloader/releases/latest>`__,
27 extract the Zip or Tarball and execute ``instaloader.py`` from there.
27 extract the Zip or Tarball and run ``setup.py`` from there.
2828
2929 - On **Arch Linux**, you may install Instaloader using the
3030 `Instaloader AUR package <https://aur.archlinux.org/packages/instaloader/>`__.
3232 - On **Windows 10**, you may download the standalone executable from the
3333 `current release page <https://github.com/instaloader/instaloader/releases/latest>`__.
3434
35 - To test the most current pre-release or development version of Instaloader::
35 - On **Android**, you can use Instaloader with `Termux <https://play.google.com/store/apps/details?id=com.termux>`__
36 after typing ``pkg install python`` and ``pip3 install instaloader``.
37
38 - To test the most current **pre-release** version of Instaloader::
3639
3740 pip3 install --pre instaloader
0 Exceptions
1 ^^^^^^^^^^
2
3 .. module:: instaloader
4 :noindex:
5
6 .. highlight:: python
7
8 .. currentmodule:: instaloader.exceptions
9
10 .. autoexception:: InstaloaderException
11 :no-show-inheritance:
12
13 .. autoexception:: ConnectionException
14
15 .. currentmodule:: instaloader
16
17 .. autoexception:: QueryReturnedBadRequestException
18
19 .. autoexception:: QueryReturnedForbiddenException
20
21 .. autoexception:: ProfileNotExistsException
22
23 .. autoexception:: ProfileHasNoPicsException
24
25 .. autoexception:: PrivateProfileNotFollowedException
26
27 .. autoexception:: LoginRequiredException
28
29 .. autoexception:: TwoFactorAuthRequiredException
30
31 .. versionadded:: 4.2
32
33 .. autoexception:: InvalidArgumentException
34
35 .. autoexception:: BadResponseException
36
37 .. autoexception:: BadCredentialsException
38
39 .. autoexception:: PostChangedException
40
41 .. autoexception:: QueryReturnedNotFoundException
42
43 .. versionchanged:: 4.3
44 QueryReturnedNotFoundException now inherits ConnectionException
45 to retry on 404 errors.
46
47
48 .. autoexception:: TooManyRequestsException
49
50 .. autoexception:: AbortDownloadException
0 ``Instaloader`` (Main Class)
1 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2
3 .. module:: instaloader
4 :noindex:
5
6 .. highlight:: python
7
8 .. autoclass:: Instaloader
9 :no-show-inheritance:
0 ``InstaloaderContext`` (Low-level functions)
1 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2
3 .. module:: instaloader
4 :noindex:
5
6 .. highlight:: python
7
8 .. contents::
9 :backlinks: none
10
11 ``InstaloaderContext``
12 """"""""""""""""""""""
13
14 .. autoclass:: InstaloaderContext
15 :no-show-inheritance:
16
17 ``RateController``
18 """"""""""""""""""
19
20 .. autoclass:: RateController
21 :no-show-inheritance:
22
23 .. versionadded:: 4.5
0 Resumable Iterations
1 ^^^^^^^^^^^^^^^^^^^^
2
3 .. module:: instaloader
4 :noindex:
5
6 .. highlight:: python
7
8 .. contents::
9 :backlinks: none
10
11 For many download targets, Instaloader is able to resume a
12 previously-interrupted iteration. It provides an interruptible
13 Iterator :class:`NodeIterator` and a context manager
14 :func:`resumable_iteration`, which we both present here.
15
16 .. versionadded:: 4.5
17
18 ``NodeIterator``
19 """"""""""""""""
20
21 .. autoclass:: NodeIterator
22 :no-show-inheritance:
23
24 .. autoclass:: FrozenNodeIterator
25 :no-show-inheritance:
26
27 A serializable representation of a :class:`NodeIterator` instance, saving
28 its iteration state.
29
30 It can be serialized and deserialized with :func:`save_structure_to_file`
31 and :func:`load_structure_from_file`, as well as with :mod:`json` and
32 :mod:`pickle` thanks to being a :func:`~collections.namedtuple`.
33
34 ``resumable_iteration``
35 """""""""""""""""""""""
36
37 .. autofunction:: resumable_iteration
0 Instagram Structures
1 ^^^^^^^^^^^^^^^^^^^^
2
3 .. module:: instaloader
4 :noindex:
5
6 .. highlight:: python
7
8 .. contents::
9 :backlinks: none
10
11 Posts
12 """""
13
14 .. autoclass:: Post
15 :no-show-inheritance:
16
17 Additionally, the following trivial structures are defined:
18
19 .. autoclass:: PostSidecarNode
20 :no-show-inheritance:
21
22 .. autoclass:: PostComment
23 :no-show-inheritance:
24
25 .. autoclass:: PostCommentAnswer
26 :no-show-inheritance:
27
28 .. autoclass:: PostLocation
29 :no-show-inheritance:
30
31 User Stories
32 """"""""""""
33
34 .. autoclass:: Story
35 :no-show-inheritance:
36
37 .. autoclass:: StoryItem
38 :no-show-inheritance:
39
40 Highlights
41 """"""""""
42
43 .. autoclass:: Highlight
44 :no-show-inheritance:
45 :inherited-members:
46
47 Bases: :class:`Story`
48
49 .. versionadded:: 4.1
50
51 Profiles
52 """"""""
53
54 .. autoclass:: Profile
55 :no-show-inheritance:
56
57 Hashtags
58 """"""""
59
60 .. autoclass:: Hashtag
61 :no-show-inheritance:
62
63 .. versionadded:: 4.4
64
65 TopSearchResults
66 """"""""""""""""
67
68 .. autoclass:: TopSearchResults
69 :no-show-inheritance:
70
71 .. versionadded:: 4.3
72
73 Loading and Saving
74 """"""""""""""""""
75
76 :class:`Post`, :class:`StoryItem`, :class:`Profile`, :class:`Hashtag` and
77 :class:`FrozenNodeIterator` can be saved and loaded to/from JSON files.
78
79 .. autofunction:: load_structure
80
81 .. autofunction:: load_structure_from_file
82
83 .. autofunction:: get_json_structure
84
85 .. autofunction:: save_structure_to_file
86
87 LatestStamps
88 """"""""""""
89
90 .. autoclass:: LatestStamps
91 :no-show-inheritance:
00 requests
1 sphinx!=1.7.7
1 sphinx~=2.3
0 .. _sponsors:
1
2 Sponsoring the development of Instaloader
3 =========================================
4
5 .. donations-start
6
7 .. include:: ../README.rst
8 :start-after: current-sponsors-start
9 :end-before: current-sponsors-end
10
11 It is a pleasure for us to share our Instaloader to the world, and we are proud
12 to have attracted such an active and motivating community, with so many users
13 who share their suggestions and ideas with us. Buying a community-sponsored beer
14 or coffee from time to time is very likely to further raise our passion for the
15 development of Instaloader.
16
17 | For Donations, we provide GitHub Sponsors page, a PayPal.Me link and a Bitcoin address.
18 | GitHub Sponsors: `Sponsor @aandergr on GitHub Sponsors <https://github.com/sponsors/aandergr>`__
19 | PayPal: `PayPal.me/aandergr <https://www.paypal.me/aandergr>`__
20 | BTC: 1Nst4LoadeYzrKjJ1DX9CpbLXBYE9RKLwY
21
22 .. donations-end
44
55 .. highlight:: python
66
7 429 - Too Many Requests
8 -----------------------
7 429 Too Many Requests
8 ---------------------
99
1010 Instaloader has a logic to keep track of its requests to Instagram and to obey
11 their rate limits. Since they are nowhere documented, we try them out
12 experimentally. We have a daily cron job running to confirm that Instaloader
13 still stays within the rate limits. Nevertheless, the rate control logic assumes
14 that
11 their rate limits. The rate controller assumes that
1512
16 - at one time, Instaloader is the only application that consumes requests. I.e.
13 - at one time, Instaloader is the only application that consumes requests, i.e.
1714 neither the Instagram browser interface, nor a mobile app, nor another
18 Instaloader instance is running in parallel,
15 Instaloader instance is running in parallel, and
1916
2017 - no requests had been consumed when Instaloader starts.
2118
2219 The latter one implies that restarting or reinstantiating Instaloader often
23 within short time is prone to cause a 429. When a request is denied with a 429,
20 within short time is prone to cause a 429.
21
22 Since the behavior of the rate controller might change between different
23 versions of Instaloader, make sure to use the current version of Instaloader,
24 especially when encountering many 429 errors.
25
26 If a request is denied with a 429,
2427 Instaloader retries the request as soon as the temporary ban is assumed to be
2528 expired. In case the retry continuously fails for some reason, which should not
26 happen in normal conditions, consider adjusting the
29 happen under normal conditions, consider adjusting the
2730 :option:`--max-connection-attempts` option.
2831
2932 There have been observations that services, that in their nature offer
30 promiscious IP addresses, such as cloud, VPN and public proxy services, might be
33 promiscuous IP addresses, such as cloud, VPN and public proxy services, might be
3134 subject to significantly stricter limits for anonymous access. However,
3235 logged-in accesses (see :option:`--login`) do not seem to be affected.
36
37 Instaloader allows to adjust the rate controlling behavior by overriding
38 :class:`instaloader.RateController`.
3339
3440 Too many queries in the last time
3541 ---------------------------------
3642
3743 **"Too many queries in the last time"** is not an error. It is a notice that the
3844 rate limit has almost been reached, according to Instaloader's own rate
39 accounting mechanism. We regularly adjust this mechanism to match Instagram's
40 current rate limiting.
45 accounting mechanism.
46
47 Instaloader allows to adjust the rate controlling behavior by overriding
48 :class:`instaloader.RateController`.
4149
4250 Private but not followed
4351 ------------------------
4553 You have to follow a private account to access most of its associated
4654 information.
4755
48 Login Error
56 Login error
4957 -----------
5058
5159 Instaloader's login *should* work fine, both with and without
5361 issued when Instagram suspects authentication activity on your account, by
5462 pointing the user to an URL to be opened in a browser.
5563
56 Nevertheless, in :issue:`92` and :issue:`615` users reported problems with
57 logging in. We recommend to always keep the sessionfile which Instaloader
58 creates when using :option:`--login`. If a sessionfile is present,
59 :option:`--login` does not make make use of the failure-prone login procedure.
60 Also, sessionfiles usually do not expire and can be copied between different
61 computers without any problems.
64 Nevertheless, in :issue:`92`, :issue:`615`, :issue:`1150` and :issue:`1217`,
65 users reported problems with
66 logging in. We recommend to always keep the session file which Instaloader
67 creates when using :option:`--login`. If a session file is present,
68 :option:`--login` does not make use of the failure-prone login procedure.
69 Also, session files usually do not expire.
6270
63 If you do not have a sessionfile present, you may use the following script
71 If you do not have a session file present, you may use the following script
6472 (:example:`615_import_firefox_session.py`) to workaround login problems by
6573 importing the session cookies from Firefox and bypassing Instaloader's login and
6674 so still use Instaloader's logged-in functionality.
7785
7886 #. Then, ``instaloader -l USERNAME`` should work fine.
7987
80 This script also supports specifying a cookiefile path, which may be useful if
88 This script also supports specifying a cookie file path, which may be useful if
8189 you use multiple Firefox profiles or if your operating system has the directory
82 structure differently set up. Also, you can specify an alternative sessionfile
90 structure differently set up. Also, you can specify an alternative session file
8391 path.
00 """Download pictures (or videos) along with their captions and other metadata from Instagram."""
11
22
3 __version__ = '4.4.5'
3 __version__ = '4.9b1'
44
55
66 try:
1313
1414 from .exceptions import *
1515 from .instaloader import Instaloader
16 from .instaloadercontext import InstaloaderContext
16 from .instaloadercontext import InstaloaderContext, RateController
17 from .lateststamps import LatestStamps
18 from .nodeiterator import NodeIterator, FrozenNodeIterator, resumable_iteration
1719 from .structures import (Hashtag, Highlight, Post, PostSidecarNode, PostComment, PostCommentAnswer, PostLocation,
18 Profile, Story, StoryItem, TopSearchResults, load_structure_from_file, save_structure_to_file)
20 Profile, Story, StoryItem, TopSearchResults, load_structure_from_file, save_structure_to_file,
21 load_structure, get_json_structure)
44 import os
55 import re
66 import sys
7 from argparse import ArgumentParser, SUPPRESS
7 from argparse import ArgumentParser, ArgumentTypeError, SUPPRESS
88 from typing import List, Optional
99
10 from . import (Instaloader, InstaloaderException, InvalidArgumentException, Post, Profile, ProfileNotExistsException,
11 StoryItem, __version__, load_structure_from_file, TwoFactorAuthRequiredException,
12 BadCredentialsException)
13 from .instaloader import get_default_session_filename
10 from . import (AbortDownloadException, BadCredentialsException, Instaloader, InstaloaderException,
11 InvalidArgumentException, Post, Profile, ProfileNotExistsException, StoryItem,
12 TwoFactorAuthRequiredException, __version__, load_structure_from_file)
13 from .instaloader import (get_default_session_filename, get_default_stamps_filename)
1414 from .instaloadercontext import default_user_agent
15 from .lateststamps import LatestStamps
1516
1617
1718 def usage_string():
2425 {2:{1}} [--login YOUR-USERNAME] [--fast-update]
2526 {2:{1}} profile | "#hashtag" | %%location_id | :stories | :feed | :saved
2627 {0} --help""".format(argv0, len(argv0), '')
28
29
30 def http_status_code_list(code_list_str: str) -> List[int]:
31 codes = [int(s) for s in code_list_str.split(',')]
32 for code in codes:
33 if not 100 <= code <= 599:
34 raise ArgumentTypeError("Invalid HTTP status code: {}".format(code))
35 return codes
2736
2837
2938 def filterstr_to_filterfunc(filter_str: str, item_type: type):
6776 download_tagged: bool = False,
6877 download_igtv: bool = False,
6978 fast_update: bool = False,
79 latest_stamps_file: Optional[str] = None,
7080 max_count: Optional[int] = None, post_filter_str: Optional[str] = None,
7181 storyitem_filter_str: Optional[str] = None) -> None:
7282 """Download set of profiles, hashtags etc. and handle logging in and session files if desired."""
7989 if storyitem_filter_str is not None:
8090 storyitem_filter = filterstr_to_filterfunc(storyitem_filter_str, StoryItem)
8191 instaloader.context.log('Only download storyitems with property "{}".'.format(storyitem_filter_str))
92 latest_stamps = None
93 if latest_stamps_file is not None:
94 latest_stamps = LatestStamps(latest_stamps_file)
95 instaloader.context.log(f"Using latest stamps from {latest_stamps_file}.")
8296 # Login, if desired
8397 if username is not None:
8498 if not re.match(r"^[A-Za-z0-9._]+$", username):
99113 code = input("Enter 2FA verification code: ")
100114 instaloader.two_factor_login(code)
101115 break
102 except BadCredentialsException:
116 except BadCredentialsException as err:
117 print(err, file=sys.stderr)
103118 pass
104119 else:
105120 instaloader.interactive_login(username)
163178 post_filter=post_filter)
164179 elif re.match(r"^[A-Za-z0-9._]+$", target):
165180 try:
166 profile = instaloader.check_profile_id(target)
181 profile = instaloader.check_profile_id(target, latest_stamps)
167182 if instaloader.context.is_logged_in and profile.has_blocked_viewer:
168183 if download_profile_pic or ((download_posts or download_tagged or download_igtv)
169184 and not profile.is_private):
182197 instaloader.context.log("Trying again anonymously, helps in case you are just blocked.")
183198 with instaloader.anonymous_copy() as anonymous_loader:
184199 with instaloader.context.error_catcher():
185 anonymous_retry_profiles.add(anonymous_loader.check_profile_id(target))
200 anonymous_retry_profiles.add(anonymous_loader.check_profile_id(target,
201 latest_stamps))
186202 instaloader.context.error("Warning: {} will be downloaded anonymously (\"{}\")."
187203 .format(target, err))
188204 else:
197213 if len(profiles) > 1:
198214 instaloader.context.log("Downloading {} profiles: {}".format(len(profiles),
199215 ' '.join([p.username for p in profiles])))
200 if profiles and (download_profile_pic or download_posts) and not instaloader.context.is_logged_in:
201 instaloader.context.error("Warning: Use --login to download higher-quality versions of pictures.")
216 if instaloader.context.iphone_support and profiles and (download_profile_pic or download_posts) and \
217 not instaloader.context.is_logged_in:
218 instaloader.context.log("Hint: Use --login to download higher-quality versions of pictures.")
202219 instaloader.download_profiles(profiles,
203220 download_profile_pic, download_posts, download_tagged, download_igtv,
204221 download_highlights, download_stories,
205 fast_update, post_filter, storyitem_filter)
222 fast_update, post_filter, storyitem_filter, latest_stamps=latest_stamps)
206223 if anonymous_retry_profiles:
207224 instaloader.context.log("Downloading anonymously: {}"
208225 .format(' '.join([p.username for p in anonymous_retry_profiles])))
209226 with instaloader.anonymous_copy() as anonymous_loader:
210227 anonymous_loader.download_profiles(anonymous_retry_profiles,
211228 download_profile_pic, download_posts, download_tagged, download_igtv,
212 fast_update=fast_update, post_filter=post_filter)
229 fast_update=fast_update, post_filter=post_filter,
230 latest_stamps=latest_stamps)
213231 except KeyboardInterrupt:
214232 print("\nInterrupted by user.", file=sys.stderr)
233 except AbortDownloadException as exc:
234 print("\nDownload aborted: {}.".format(exc), file=sys.stderr)
215235 # Save session if it is useful
216236 if instaloader.context.is_logged_in:
217237 instaloader.save_session_to_file(sessionfile)
221241 # Instaloader did at least save a session file
222242 instaloader.context.log("No targets were specified, thus nothing has been downloaded.")
223243 else:
224 # Instloader did not do anything
244 # Instaloader did not do anything
225245 instaloader.context.log("usage:" + usage_string())
226246
227247
228248 def main():
229249 parser = ArgumentParser(description=__doc__, add_help=False, usage=usage_string(),
230 epilog="Report issues at https://github.com/instaloader/instaloader/issues. "
231 "The complete documentation can be found at "
250 epilog="The complete documentation can be found at "
232251 "https://instaloader.github.io/.",
233252 fromfile_prefix_chars='+')
234253
267286 help="Do not download regular posts.")
268287 g_prof.add_argument('--no-profile-pic', action='store_true',
269288 help='Do not download profile picture.')
289 g_post.add_argument('--slide', action='store',
290 help='Set what image/interval of a sidecar you want to download.')
270291 g_post.add_argument('--no-pictures', action='store_true',
271292 help='Do not download post pictures. Cannot be used together with --fast-update. '
272293 'Implies --no-video-thumbnails, does not imply --no-videos.')
311332 g_cond.add_argument('-F', '--fast-update', action='store_true',
312333 help='For each target, stop when encountering the first already-downloaded picture. This '
313334 'flag is recommended when you use Instaloader to update your personal Instagram archive.')
314
335 g_cond.add_argument('--latest-stamps', nargs='?', metavar='STAMPSFILE', const=get_default_stamps_filename(),
336 help='Store the timestamps of latest media scraped for each profile. This allows updating '
337 'your personal Instagram archive even if you delete the destination directories. '
338 'If STAMPSFILE is not provided, defaults to ' + get_default_stamps_filename())
315339 g_cond.add_argument('--post-filter', '--only-if', metavar='filter',
316340 help='Expression that, if given, must evaluate to True for each post to be downloaded. Must be '
317341 'a syntactically valid python expression. Variables are evaluated to '
323347
324348 g_cond.add_argument('-c', '--count',
325349 help='Do not attempt to download more than COUNT posts. '
326 'Applies only to #hashtag and :feed.')
350 'Applies to #hashtag, %%location_id, :feed, and :saved.')
327351
328352 g_login = parser.add_argument_group('Login (Download Private Profiles)',
329353 'Instaloader can login to Instagram. This allows downloading private profiles. '
346370 '{target} is replaced by the target you specified, i.e. either :feed, #hashtag or the '
347371 'profile name. Defaults to \'{target}\'.')
348372 g_how.add_argument('--filename-pattern',
349 help='Prefix of filenames, relative to the directory given with '
373 help='Prefix of filenames for posts and stories, relative to the directory given with '
350374 '--dirname-pattern. {profile} is replaced by the profile name,'
351375 '{target} is replaced by the target you specified, i.e. either :feed'
352376 '#hashtag or the profile name. Defaults to \'{date_utc}_UTC\'')
377 g_how.add_argument('--title-pattern',
378 help='Prefix of filenames for profile pics, hashtag profile pics, and highlight covers. '
379 'Defaults to \'{date_utc}_UTC_{typename}\' if --dirname-pattern contains \'{target}\' '
380 'or \'{dirname}\', or if --dirname-pattern is not specified. Otherwise defaults to '
381 '\'{target}_{date_utc}_UTC_{typename}\'.')
382 g_how.add_argument('--resume-prefix', metavar='PREFIX',
383 help='Prefix for filenames that are used to save the information to resume an interrupted '
384 'download.')
385 g_how.add_argument('--no-resume', action='store_true',
386 help='Do not resume a previously-aborted download iteration, and do not save such information '
387 'when interrupted.')
388 g_how.add_argument('--use-aged-resume-files', action='store_true', help=SUPPRESS)
353389 g_how.add_argument('--user-agent',
354390 help='User Agent to use for HTTP requests. Defaults to \'{}\'.'.format(default_user_agent()))
355391 g_how.add_argument('-S', '--no-sleep', action='store_true', help=SUPPRESS)
357393 help='Maximum number of connection attempts until a request is aborted. Defaults to 3. If a '
358394 'connection fails, it can be manually skipped by hitting CTRL+C. Set this to 0 to retry '
359395 'infinitely.')
360 g_how.add_argument('--commit-mode', action='store_true',
361 help='Tries to ensure downloaded images avoid corruption in case of unexpected interruption. '
362 'If the last picture is corrupted, Instaloader will fix the picture the next time it is run. '
363 'Requires the JSON metadata to be saved.')
364 g_how.add_argument('--request-timeout', metavar='N', type=float,
365 help='seconds to wait before timing out a connection request')
396 g_how.add_argument('--commit-mode', action='store_true', help=SUPPRESS)
397 g_how.add_argument('--request-timeout', metavar='N', type=float, default=300.0,
398 help='Seconds to wait before timing out a connection request. Defaults to 300.')
399 g_how.add_argument('--abort-on', type=http_status_code_list, metavar="STATUS_CODES",
400 help='Comma-separated list of HTTP status codes that cause Instaloader to abort, bypassing all '
401 'retry logic.')
402 g_how.add_argument('--no-iphone', action='store_true',
403 help='Do not attempt to download iPhone version of images and videos.')
366404
367405 g_misc = parser.add_argument_group('Miscellaneous Options')
368406 g_misc.add_argument('-q', '--quiet', action='store_true',
396434 raise SystemExit("--no-captions and --post-metadata-txt or --storyitem-metadata-txt given; "
397435 "That contradicts.")
398436
437 if args.no_resume and args.resume_prefix:
438 raise SystemExit("--no-resume and --resume-prefix given; That contradicts.")
439 resume_prefix = (args.resume_prefix if args.resume_prefix else 'iterator') if not args.no_resume else None
440
399441 if args.no_pictures and args.fast_update:
400442 raise SystemExit('--no-pictures and --fast-update cannot be used together.')
401443
403445 download_profile_pic = not args.no_profile_pic or args.profile_pic_only
404446 download_posts = not (args.no_posts or args.stories_only or args.profile_pic_only)
405447 download_stories = args.stories or args.stories_only
406
407 if args.commit_mode and args.no_metadata_json:
408 raise SystemExit('--commit-mode requires JSON metadata to be saved.')
409448
410449 loader = Instaloader(sleep=not args.no_sleep, quiet=args.quiet, user_agent=args.user_agent,
411450 dirname_pattern=args.dirname_pattern, filename_pattern=args.filename_pattern,
418457 storyitem_metadata_txt_pattern=storyitem_metadata_txt_pattern,
419458 max_connection_attempts=args.max_connection_attempts,
420459 request_timeout=args.request_timeout,
421 commit_mode=args.commit_mode)
460 resume_prefix=resume_prefix,
461 check_resume_bbd=not args.use_aged_resume_files,
462 slide=args.slide,
463 fatal_status_codes=args.abort_on,
464 iphone_support=not args.no_iphone,
465 title_pattern=args.title_pattern)
422466 _main(loader,
423467 args.profile,
424468 username=args.login.lower() if args.login is not None else None,
431475 download_tagged=args.tagged,
432476 download_igtv=args.igtv,
433477 fast_update=args.fast_update,
478 latest_stamps_file=args.latest_stamps,
434479 max_count=int(args.count) if args.count is not None else None,
435480 post_filter_str=args.post_filter,
436481 storyitem_filter_str=args.storyitem_filter)
437482 loader.close()
438483 except InstaloaderException as err:
439 raise SystemExit("Fatal error: %s" % err)
484 raise SystemExit("Fatal error: %s" % err) from err
440485
441486
442487 if __name__ == "__main__":
6363
6464 class TooManyRequestsException(ConnectionException):
6565 pass
66
67 class IPhoneSupportDisabledException(InstaloaderException):
68 pass
69
70 class AbortDownloadException(Exception):
71 """
72 Exception that is not catched in the error catchers inside the download loop and so aborts the
73 download loop.
74
75 This exception is not a subclass of ``InstaloaderException``.
76
77 .. versionadded:: 4.7
78 """
79 pass
00 import getpass
11 import json
2 import lzma
32 import os
43 import platform
54 import re
109 from contextlib import contextmanager, suppress
1110 from datetime import datetime, timezone
1211 from functools import wraps
13 from hashlib import md5
1412 from io import BytesIO
1513 from pathlib import Path
16 from typing import Any, Callable, Iterator, List, Optional, Set, Union
14 from typing import Any, Callable, IO, Iterator, List, Optional, Set, Union, cast
15 from urllib.parse import urlparse
1716
1817 import requests
1918 import urllib3 # type: ignore
2019
2120 from .exceptions import *
22 from .instaloadercontext import InstaloaderContext
21 from .instaloadercontext import InstaloaderContext, RateController
22 from .lateststamps import LatestStamps
23 from .nodeiterator import NodeIterator, resumable_iteration
24 from .sectioniterator import SectionIterator
2325 from .structures import (Hashtag, Highlight, JsonExportable, Post, PostLocation, Profile, Story, StoryItem,
24 save_structure_to_file, load_structure_from_file)
26 load_structure_from_file, save_structure_to_file, PostSidecarNode, TitlePic)
27
28
29 def _get_config_dir() -> str:
30 if platform.system() == "Windows":
31 # on Windows, use %LOCALAPPDATA%\Instaloader
32 localappdata = os.getenv("LOCALAPPDATA")
33 if localappdata is not None:
34 return os.path.join(localappdata, "Instaloader")
35 # legacy fallback - store in temp dir if %LOCALAPPDATA% is not set
36 return os.path.join(tempfile.gettempdir(), ".instaloader-" + getpass.getuser())
37 # on Unix, use ~/.config/instaloader
38 return os.path.join(os.getenv("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), "instaloader")
2539
2640
2741 def get_default_session_filename(username: str) -> str:
2842 """Returns default session filename for given username."""
43 configdir = _get_config_dir()
2944 sessionfilename = "session-{}".format(username)
30 if platform.system() == "Windows":
31 # on Windows, use %LOCALAPPDATA%\Instaloader\session-USERNAME
32 localappdata = os.getenv("LOCALAPPDATA")
33 if localappdata is not None:
34 return os.path.join(localappdata, "Instaloader", sessionfilename)
35 # legacy fallback - store in temp dir if %LOCALAPPDATA% is not set
36 return os.path.join(tempfile.gettempdir(), ".instaloader-" + getpass.getuser(), sessionfilename)
37 # on Unix, use ~/.config/instaloader/session-USERNAME
38 return os.path.join(os.getenv("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), "instaloader", sessionfilename)
45 return os.path.join(configdir, sessionfilename)
3946
4047
4148 def get_legacy_session_filename(username: str) -> str:
4350 dirname = tempfile.gettempdir() + "/" + ".instaloader-" + getpass.getuser()
4451 filename = dirname + "/" + "session-" + username
4552 return filename.lower()
53
54
55 def get_default_stamps_filename() -> str:
56 """
57 Returns default filename for latest stamps database.
58
59 .. versionadded:: 4.8
60
61 """
62 configdir = _get_config_dir()
63 return os.path.join(configdir, "latest-stamps.ini")
4664
4765
4866 def format_string_contains_key(format_string: str, key: str) -> bool:
100118
101119 def get_value(self, key, args, kwargs):
102120 """Override to substitute {ATTRIBUTE} by attributes of our _item."""
121 if key == 'filename' and isinstance(self._item, (Post, StoryItem, PostSidecarNode, TitlePic)):
122 return "{filename}"
103123 if hasattr(self._item, key):
104124 return getattr(self._item, key)
105125 return super().get_value(key, args, kwargs)
126146 def sanitize_path(ret: str) -> str:
127147 """Replaces '/' with similar looking Division Slash and some other illegal filename characters on Windows."""
128148 ret = ret.replace('/', '\u2215')
149
150 if ret.startswith('.'):
151 ret = ret.replace('.', '\u2024', 1)
152
129153 if platform.system() == 'Windows':
130154 ret = ret.replace(':', '\uff1a').replace('<', '\ufe64').replace('>', '\ufe65').replace('\"', '\uff02')
131155 ret = ret.replace('\\', '\ufe68').replace('|', '\uff5c').replace('?', '\ufe16').replace('*', '\uff0a')
140164 :param user_agent: :option:`--user-agent`
141165 :param dirname_pattern: :option:`--dirname-pattern`, default is ``{target}``
142166 :param filename_pattern: :option:`--filename-pattern`, default is ``{date_utc}_UTC``
167 :param title_pattern:
168 :option:`--title-pattern`, default is ``{date_utc}_UTC_{typename}`` if ``dirname_pattern`` contains
169 ``{target}`` or ``{profile}``, ``{target}_{date_utc}_UTC_{typename}`` otherwise.
143170 :param download_pictures: not :option:`--no-pictures`
144171 :param download_videos: not :option:`--no-videos`
145172 :param download_video_thumbnails: not :option:`--no-video-thumbnails`
152179 txt file.
153180 :param storyitem_metadata_txt_pattern: :option:`--storyitem-metadata-txt`, default is empty (=none)
154181 :param max_connection_attempts: :option:`--max-connection-attempts`
155 :param commit_mode: :option:`--commit-mode`
156182 :param request_timeout: :option:`--request-timeout`, set per-request timeout (seconds)
183 :param rate_controller: Generator for a :class:`RateController` to override rate controlling behavior
184 :param resume_prefix: :option:`--resume-prefix`, or None for :option:`--no-resume`.
185 :param check_resume_bbd: Whether to check the date of expiry of resume files and reject them if expired.
186 :param slide: :option:`--slide`
187 :param fatal_status_codes: :option:`--abort-on`
188 :param iphone_support: not :option:`--no-iphone`
157189
158190 .. attribute:: context
159191
169201 download_pictures=True,
170202 download_videos: bool = True,
171203 download_video_thumbnails: bool = True,
172 download_geotags: bool = True,
173 download_comments: bool = True,
204 download_geotags: bool = False,
205 download_comments: bool = False,
174206 save_metadata: bool = True,
175207 compress_json: bool = True,
176208 post_metadata_txt_pattern: str = None,
177209 storyitem_metadata_txt_pattern: str = None,
178210 max_connection_attempts: int = 3,
179 request_timeout: Optional[float] = None,
180 commit_mode: bool = False):
181
182 self.context = InstaloaderContext(sleep, quiet, user_agent, max_connection_attempts, request_timeout)
211 request_timeout: float = 300.0,
212 rate_controller: Optional[Callable[[InstaloaderContext], RateController]] = None,
213 resume_prefix: Optional[str] = "iterator",
214 check_resume_bbd: bool = True,
215 slide: Optional[str] = None,
216 fatal_status_codes: Optional[List[int]] = None,
217 iphone_support: bool = True,
218 title_pattern: Optional[str] = None):
219
220 self.context = InstaloaderContext(sleep, quiet, user_agent, max_connection_attempts,
221 request_timeout, rate_controller, fatal_status_codes,
222 iphone_support)
183223
184224 # configuration parameters
185225 self.dirname_pattern = dirname_pattern or "{target}"
186226 self.filename_pattern = filename_pattern or "{date_utc}_UTC"
227 if title_pattern is not None:
228 self.title_pattern = title_pattern
229 else:
230 if (format_string_contains_key(self.dirname_pattern, 'profile') or
231 format_string_contains_key(self.dirname_pattern, 'target')):
232 self.title_pattern = '{date_utc}_UTC_{typename}'
233 else:
234 self.title_pattern = '{target}_{date_utc}_UTC_{typename}'
187235 self.download_pictures = download_pictures
188236 self.download_videos = download_videos
189237 self.download_video_thumbnails = download_video_thumbnails
195243 else post_metadata_txt_pattern
196244 self.storyitem_metadata_txt_pattern = '' if storyitem_metadata_txt_pattern is None \
197245 else storyitem_metadata_txt_pattern
198 self.commit_mode = commit_mode
199 if self.commit_mode and not self.save_metadata:
200 raise InvalidArgumentException("Commit mode requires JSON metadata to be saved.")
201
202 # Used to keep state in commit mode
203 self._committed = None # type: Optional[bool]
246 self.resume_prefix = resume_prefix
247 self.check_resume_bbd = check_resume_bbd
248
249 self.slide = slide or ""
250 self.slide_start = 0
251 self.slide_end = -1
252 if self.slide != "":
253 splitted = self.slide.split('-')
254 if len(splitted) == 1:
255 if splitted[0] == 'last':
256 # download only last image of a sidecar
257 self.slide_start = -1
258 else:
259 if int(splitted[0]) > 0:
260 self.slide_start = self.slide_end = int(splitted[0])-1
261 else:
262 raise InvalidArgumentException("--slide parameter must be greater than 0.")
263 elif len(splitted) == 2:
264 if splitted[1] == 'last':
265 self.slide_start = int(splitted[0])-1
266 elif 0 < int(splitted[0]) < int(splitted[1]):
267 self.slide_start = int(splitted[0])-1
268 self.slide_end = int(splitted[1])-1
269 else:
270 raise InvalidArgumentException("Invalid data for --slide parameter.")
271 else:
272 raise InvalidArgumentException("Invalid data for --slide parameter.")
204273
205274 @contextmanager
206275 def anonymous_copy(self):
222291 storyitem_metadata_txt_pattern=self.storyitem_metadata_txt_pattern,
223292 max_connection_attempts=self.context.max_connection_attempts,
224293 request_timeout=self.context.request_timeout,
225 commit_mode=self.commit_mode)
294 resume_prefix=self.resume_prefix,
295 check_resume_bbd=self.check_resume_bbd,
296 slide=self.slide,
297 fatal_status_codes=self.context.fatal_status_codes,
298 iphone_support=self.context.iphone_support)
226299 yield new_loader
227300 self.context.error_log.extend(new_loader.context.error_log)
228301 new_loader.context.error_log = [] # avoid double-printing of errors
248321 if filename_suffix is not None:
249322 filename += '_' + filename_suffix
250323 filename += '.' + file_extension
251 # A post is considered "commited" if the json file exists and is not malformed.
252 if self.commit_mode:
253 if self._committed and os.path.isfile(filename):
254 self.context.log(filename + ' exists', end=' ', flush=True)
255 return False
256 else:
257 if os.path.isfile(filename):
258 self.context.log(filename + ' exists', end=' ', flush=True)
259 return False
324 if os.path.isfile(filename):
325 self.context.log(filename + ' exists', end=' ', flush=True)
326 return False
260327 self.context.get_and_write_raw(url, filename)
261328 os.utime(filename, (datetime.now().timestamp(), mtime.timestamp()))
262329 return True
304371 combined_answers.extend(y['answers'])
305372 unique_comments_list[-1]['answers'] = get_unique_comments(combined_answers)
306373 return unique_comments_list
374
375 def get_new_comments(new_comments, start):
376 for idx, comment in enumerate(new_comments, start=start+1):
377 if idx % 250 == 0:
378 self.context.log('{}'.format(idx), end='…', flush=True)
379 yield comment
380
381 def save_comments(extended_comments):
382 unique_comments = get_unique_comments(extended_comments, combine_answers=True)
383 answer_ids = set(int(answer['id']) for comment in unique_comments for answer in comment.get('answers', []))
384 with open(filename, 'w') as file:
385 file.write(json.dumps(list(filter(lambda t: int(t['id']) not in answer_ids, unique_comments)),
386 indent=4))
387
388 base_filename = filename
307389 filename += '_comments.json'
308390 try:
309391 with open(filename) as fp:
310392 comments = json.load(fp)
311393 except (FileNotFoundError, json.decoder.JSONDecodeError):
312394 comments = list()
313 comments.extend(_postcomment_asdict(comment) for comment in post.get_comments())
395
396 comments_iterator = post.get_comments()
397 try:
398 with resumable_iteration(
399 context=self.context,
400 iterator=comments_iterator,
401 load=load_structure_from_file,
402 save=save_structure_to_file,
403 format_path=lambda magic: "{}_{}_{}.json.xz".format(base_filename, self.resume_prefix, magic),
404 check_bbd=self.check_resume_bbd,
405 enabled=self.resume_prefix is not None
406 ) as (_is_resuming, start_index):
407 comments.extend(_postcomment_asdict(comment)
408 for comment in get_new_comments(comments_iterator, start_index))
409 except (KeyboardInterrupt, AbortDownloadException):
410 if comments:
411 save_comments(comments)
412 raise
314413 if comments:
315 comments = get_unique_comments(comments, combine_answers=True)
316 answer_ids = set(int(answer['id']) for comment in comments for answer in comment.get('answers', []))
317 with open(filename, 'w') as file:
318 file.write(json.dumps(list(filter(lambda t: int(t['id']) not in answer_ids, comments)), indent=4))
414 save_comments(comments)
319415 self.context.log('comments', end=' ', flush=True)
320416
321417 def save_caption(self, filename: str, mtime: datetime, caption: str) -> None:
354450 except UnicodeEncodeError:
355451 self.context.log('txt', end=' ', flush=True)
356452 with open(filename, 'wb') as text_file:
357 shutil.copyfileobj(BytesIO(bcaption), text_file)
453 with BytesIO(bcaption) as bio:
454 shutil.copyfileobj(cast(IO, bio), text_file)
358455 os.utime(filename, (datetime.now().timestamp(), mtime.timestamp()))
359456
360457 def save_location(self, filename: str, location: PostLocation, mtime: datetime) -> None:
364461 "https://maps.google.com/maps?q={0},{1}&ll={0},{1}\n".format(location.lat,
365462 location.lng))
366463 with open(filename, 'wb') as text_file:
367 shutil.copyfileobj(BytesIO(location_string.encode()), text_file)
464 with BytesIO(location_string.encode()) as bio:
465 shutil.copyfileobj(cast(IO, bio), text_file)
368466 os.utime(filename, (datetime.now().timestamp(), mtime.timestamp()))
369467 self.context.log('geo', end=' ', flush=True)
468
469 def format_filename_within_target_path(self,
470 target: Union[str, Path],
471 owner_profile: Optional[Profile],
472 identifier: str,
473 name_suffix: str,
474 extension: str):
475 """Returns a filename within the target path.
476
477 .. versionadded:: 4.5"""
478 if ((format_string_contains_key(self.dirname_pattern, 'profile') or
479 format_string_contains_key(self.dirname_pattern, 'target'))):
480 profile_str = owner_profile.username.lower() if owner_profile is not None else target
481 return os.path.join(self.dirname_pattern.format(profile=profile_str, target=target),
482 '{0}_{1}.{2}'.format(identifier, name_suffix, extension))
483 else:
484 return os.path.join(self.dirname_pattern.format(),
485 '{0}_{1}_{2}.{3}'.format(target, identifier, name_suffix, extension))
370486
371487 @_retry_on_connection_error
372488 def download_title_pic(self, url: str, target: Union[str, Path], name_suffix: str, owner_profile: Optional[Profile],
376492
377493 .. versionadded:: 4.3"""
378494
379 def _epoch_to_string(epoch: datetime) -> str:
380 return epoch.strftime('%Y-%m-%d_%H-%M-%S_UTC')
381
382495 http_response = self.context.get_raw(url)
383496 date_object = None # type: Optional[datetime]
384497 if 'Last-Modified' in http_response.headers:
385498 date_object = datetime.strptime(http_response.headers["Last-Modified"], '%a, %d %b %Y %H:%M:%S GMT')
499 date_object = date_object.replace(tzinfo=timezone.utc)
386500 pic_bytes = None
387 pic_identifier = _epoch_to_string(date_object)
388501 else:
389502 pic_bytes = http_response.content
390 pic_identifier = md5(pic_bytes).hexdigest()[:16]
391 pic_extension = 'jpg'
392 if ((format_string_contains_key(self.dirname_pattern, 'profile') or
393 format_string_contains_key(self.dirname_pattern, 'target'))):
394 profile_str = owner_profile.username.lower() if owner_profile is not None else target
395 filename = os.path.join(self.dirname_pattern.format(profile=profile_str,
396 target=target),
397 '{0}_{1}.{2}'.format(pic_identifier, name_suffix, pic_extension))
398 else:
399 filename = os.path.join(self.dirname_pattern.format(),
400 '{0}_{1}_{2}.{3}'.format(target, pic_identifier, name_suffix, pic_extension))
503 ig_filename = url.split('/')[-1].split('?')[0]
504 pic_data = TitlePic(owner_profile, target, name_suffix, ig_filename, date_object)
505 dirname = _PostPathFormatter(pic_data).format(self.dirname_pattern, target=target)
506 filename_template = os.path.join(dirname,
507 _PostPathFormatter(pic_data).format(self.title_pattern, target=target))
508 filename = self.__prepare_filename(filename_template, lambda: url) + ".jpg"
401509 content_length = http_response.headers.get('Content-Length', None)
402510 if os.path.isfile(filename) and (not self.context.is_logged_in or
403511 (content_length is not None and
404512 os.path.getsize(filename) >= int(content_length))):
405513 self.context.log(filename + ' already exists')
406 return None
514 return
407515 os.makedirs(os.path.dirname(filename), exist_ok=True)
408516 self.context.write_raw(pic_bytes if pic_bytes else http_response, filename)
409517 if date_object:
410518 os.utime(filename, (datetime.now().timestamp(), date_object.timestamp()))
411519 self.context.log('') # log output of _get_and_write_raw() does not produce \n
520
521 def download_profilepic_if_new(self, profile: Profile, latest_stamps: Optional[LatestStamps]) -> None:
522 """
523 Downloads and saves profile pic if it has not been downloaded before.
524
525 :param latest_stamps: Database with the last downloaded data. If not present,
526 the profile pic is downloaded unless it already exists
527
528 .. versionadded:: 4.8
529 """
530 if latest_stamps is None:
531 self.download_profilepic(profile)
532 return
533 profile_pic_basename = profile.profile_pic_url.split('/')[-1].split('?')[0]
534 saved_basename = latest_stamps.get_profile_pic(profile.username)
535 if saved_basename == profile_pic_basename:
536 return
537 self.download_profilepic(profile)
538 latest_stamps.set_profile_pic(profile.username, profile_pic_basename)
412539
413540 def download_profilepic(self, profile: Profile) -> None:
414541 """Downloads and saves profile pic."""
484611 .. versionadded:: 4.2"""
485612 self.context.two_factor_login(two_factor_code)
486613
487 def format_filename(self, item: Union[Post, StoryItem], target: Optional[Union[str, Path]] = None):
614 @staticmethod
615 def __prepare_filename(filename_template: str, url: Callable[[], str]) -> str:
616 """Replace filename token inside filename_template with url's filename and assure the directories exist.
617
618 .. versionadded:: 4.6"""
619 if "{filename}" in filename_template:
620 filename = filename_template.replace("{filename}",
621 os.path.splitext(os.path.basename(urlparse(url()).path))[0])
622 else:
623 filename = filename_template
624 os.makedirs(os.path.dirname(filename), exist_ok=True)
625 return filename
626
627 def format_filename(self, item: Union[Post, StoryItem, PostSidecarNode, TitlePic],
628 target: Optional[Union[str, Path]] = None):
488629 """Format filename of a :class:`Post` or :class:`StoryItem` according to ``filename-pattern`` parameter.
489630
490631 .. versionadded:: 4.1"""
499640 :return: True if something was downloaded, False otherwise, i.e. file was already there
500641 """
501642
643 def _already_downloaded(path: str) -> bool:
644 if not os.path.isfile(path):
645 return False
646 else:
647 self.context.log(path + ' exists', end=' ', flush=True)
648 return True
649
650 def _all_already_downloaded(path_base, is_videos_enumerated) -> bool:
651 if '{filename}' in self.filename_pattern:
652 # full URL needed to evaluate actual filename, cannot determine at
653 # this point if all sidecar nodes were already downloaded.
654 return False
655 for idx, is_video in is_videos_enumerated:
656 if self.download_pictures and (not is_video or self.download_video_thumbnails):
657 if not _already_downloaded("{0}_{1}.jpg".format(path_base, idx)):
658 return False
659 if is_video and self.download_videos:
660 if not _already_downloaded("{0}_{1}.mp4".format(path_base, idx)):
661 return False
662 return True
663
502664 dirname = _PostPathFormatter(post).format(self.dirname_pattern, target=target)
503 filename = os.path.join(dirname, self.format_filename(post, target=target))
504 os.makedirs(os.path.dirname(filename), exist_ok=True)
665 filename_template = os.path.join(dirname, self.format_filename(post, target=target))
666 filename = self.__prepare_filename(filename_template, lambda: post.url)
505667
506668 # Download the image(s) / video thumbnail and videos within sidecars if desired
507669 downloaded = True
508 self._committed = self.check_if_committed(filename)
509 if self.download_pictures:
510 if post.typename == 'GraphSidecar':
511 edge_number = 1
512 for sidecar_node in post.get_sidecar_nodes():
513 # Download picture or video thumbnail
514 if not sidecar_node.is_video or self.download_video_thumbnails is True:
515 downloaded &= self.download_pic(filename=filename, url=sidecar_node.display_url,
516 mtime=post.date_local, filename_suffix=str(edge_number))
517 # Additionally download video if available and desired
518 if sidecar_node.is_video and self.download_videos is True:
519 downloaded &= self.download_pic(filename=filename, url=sidecar_node.video_url,
520 mtime=post.date_local, filename_suffix=str(edge_number))
521 edge_number += 1
522 elif post.typename == 'GraphImage':
523 downloaded = self.download_pic(filename=filename, url=post.url, mtime=post.date_local)
524 elif post.typename == 'GraphVideo':
525 if self.download_video_thumbnails is True:
526 downloaded = self.download_pic(filename=filename, url=post.url, mtime=post.date_local)
527 else:
528 self.context.error("Warning: {0} has unknown typename: {1}".format(post, post.typename))
670 if post.typename == 'GraphSidecar':
671 if self.download_pictures or self.download_videos:
672 if not _all_already_downloaded(
673 filename_template, enumerate(
674 (post.get_is_videos()[i]
675 for i in range(self.slide_start % post.mediacount, self.slide_end % post.mediacount + 1)),
676 start=self.slide_start % post.mediacount + 1
677 )
678 ):
679 for edge_number, sidecar_node in enumerate(
680 post.get_sidecar_nodes(self.slide_start, self.slide_end),
681 start=self.slide_start % post.mediacount + 1
682 ):
683 suffix = str(edge_number) # type: Optional[str]
684 if '{filename}' in self.filename_pattern:
685 suffix = None
686 if self.download_pictures and (not sidecar_node.is_video or self.download_video_thumbnails):
687 # pylint:disable=cell-var-from-loop
688 sidecar_filename = self.__prepare_filename(filename_template,
689 lambda: sidecar_node.display_url)
690 # Download sidecar picture or video thumbnail (--no-pictures implies --no-video-thumbnails)
691 downloaded &= self.download_pic(filename=sidecar_filename, url=sidecar_node.display_url,
692 mtime=post.date_local, filename_suffix=suffix)
693 if sidecar_node.is_video and self.download_videos:
694 # pylint:disable=cell-var-from-loop
695 sidecar_filename = self.__prepare_filename(filename_template,
696 lambda: sidecar_node.video_url)
697 # Download sidecar video if desired
698 downloaded &= self.download_pic(filename=sidecar_filename, url=sidecar_node.video_url,
699 mtime=post.date_local, filename_suffix=suffix)
700 else:
701 downloaded = False
702 elif post.typename == 'GraphImage':
703 # Download picture
704 if self.download_pictures:
705 downloaded = (not _already_downloaded(filename + ".jpg") and
706 self.download_pic(filename=filename, url=post.url, mtime=post.date_local))
707 elif post.typename == 'GraphVideo':
708 # Download video thumbnail (--no-pictures implies --no-video-thumbnails)
709 if self.download_pictures and self.download_video_thumbnails:
710 with self.context.error_catcher("Video thumbnail of {}".format(post)):
711 downloaded = (not _already_downloaded(filename + ".jpg") and
712 self.download_pic(filename=filename, url=post.url, mtime=post.date_local))
713 else:
714 self.context.error("Warning: {0} has unknown typename: {1}".format(post, post.typename))
529715
530716 # Save caption if desired
531717 metadata_string = _ArbitraryItemFormatter(post).format(self.post_metadata_txt_pattern).strip()
533719 self.save_caption(filename=filename, mtime=post.date_local, caption=metadata_string)
534720
535721 # Download video if desired
536 if post.is_video and self.download_videos is True:
537 downloaded &= self.download_pic(filename=filename, url=post.video_url, mtime=post.date_local)
722 if post.is_video and self.download_videos:
723 downloaded &= (not _already_downloaded(filename + ".mp4") and
724 self.download_pic(filename=filename, url=post.video_url, mtime=post.date_local))
538725
539726 # Download geotags if desired
540727 if self.download_geotags and post.location:
541728 self.save_location(filename, post.location, post.date_local)
542729
543730 # Update comments if desired
544 if self.download_comments is True:
731 if self.download_comments:
545732 self.update_comments(filename=filename, post=post)
546733
547734 # Save metadata as JSON if desired.
548 if self.save_metadata is not False:
735 if self.save_metadata:
549736 self.save_metadata_json(filename, post)
550737
551738 self.context.log()
570757
571758 def _userid_chunks():
572759 assert userids is not None
573 userids_per_query = 100
760 userids_per_query = 50
574761 for i in range(0, len(userids), userids_per_query):
575762 yield userids[i:i + userids_per_query]
576763
577764 for userid_chunk in _userid_chunks():
578 stories = self.context.graphql_query("bf41e22b1c4ba4c9f31b844ebb7d9056",
765 stories = self.context.graphql_query("303a4ae99711322310f25250d988f3b7",
579766 {"reel_ids": userid_chunk, "precomposed_overlay": False})["data"]
580767 yield from (Story(self.context, media) for media in stories['reels_media'])
581768
584771 userids: Optional[List[Union[int, Profile]]] = None,
585772 fast_update: bool = False,
586773 filename_target: Optional[str] = ':stories',
587 storyitem_filter: Optional[Callable[[StoryItem], bool]] = None) -> None:
774 storyitem_filter: Optional[Callable[[StoryItem], bool]] = None,
775 latest_stamps: Optional[LatestStamps] = None) -> None:
588776 """
589777 Download available stories from user followees or all stories of users whose ID are given.
590778 Does not mark stories as seen.
595783 :param filename_target: Replacement for {target} in dirname_pattern and filename_pattern
596784 or None if profile name should be used instead
597785 :param storyitem_filter: function(storyitem), which returns True if given StoryItem should be downloaded
786 :param latest_stamps: Database with the last times each user was scraped
598787 :raises LoginRequiredException: If called without being logged in.
788
789 .. versionchanged:: 4.8
790 Add `latest_stamps` parameter.
599791 """
600792
601793 if not userids:
602794 self.context.log("Retrieving all visible stories...")
795 profile_count = None
603796 else:
604797 userids = [p if isinstance(p, int) else p.userid for p in userids]
605
606 for user_story in self.get_stories(userids):
798 profile_count = len(userids)
799
800 for i, user_story in enumerate(self.get_stories(userids), start=1):
607801 name = user_story.owner_username
608 self.context.log("Retrieving stories from profile {}.".format(name))
802 if profile_count is not None:
803 msg = "[{0:{w}d}/{1:{w}d}] Retrieving stories from profile {2}.".format(i, profile_count, name,
804 w=len(str(profile_count)))
805 else:
806 msg = "[{:3d}] Retrieving stories from profile {}.".format(i, name)
807 self.context.log(msg)
609808 totalcount = user_story.itemcount
610809 count = 1
810 if latest_stamps is not None:
811 # pylint:disable=cell-var-from-loop
812 last_scraped = latest_stamps.get_last_story_timestamp(name)
813 scraped_timestamp = datetime.now().astimezone()
611814 for item in user_story.get_items():
815 if latest_stamps is not None and item.date_utc.replace(tzinfo=timezone.utc) <= last_scraped:
816 break
612817 if storyitem_filter is not None and not storyitem_filter(item):
613818 self.context.log("<{} skipped>".format(item), flush=True)
614819 continue
618823 downloaded = self.download_storyitem(item, filename_target if filename_target else name)
619824 if fast_update and not downloaded:
620825 break
826 if latest_stamps is not None:
827 latest_stamps.set_last_story_timestamp(name, scraped_timestamp)
621828
622829 def download_storyitem(self, item: StoryItem, target: Union[str, Path]) -> bool:
623830 """Download one user story.
627834 :return: True if something was downloaded, False otherwise, i.e. file was already there
628835 """
629836
837 def _already_downloaded(path: str) -> bool:
838 if not os.path.isfile(path):
839 return False
840 else:
841 self.context.log(path + ' exists', end=' ', flush=True)
842 return True
843
630844 date_local = item.date_local
631845 dirname = _PostPathFormatter(item).format(self.dirname_pattern, target=target)
632 filename = os.path.join(dirname, self.format_filename(item, target=target))
633 os.makedirs(os.path.dirname(filename), exist_ok=True)
846 filename_template = os.path.join(dirname, self.format_filename(item, target=target))
847 filename = self.__prepare_filename(filename_template, lambda: item.url)
634848 downloaded = False
635849 if not item.is_video or self.download_video_thumbnails is True:
636 url = item.url
637 downloaded = self.download_pic(filename=filename, url=url, mtime=date_local)
850 downloaded = (not _already_downloaded(filename + ".jpg") and
851 self.download_pic(filename=filename, url=item.url, mtime=date_local))
638852 if item.is_video and self.download_videos is True:
639 downloaded |= self.download_pic(filename=filename, url=item.video_url, mtime=date_local)
853 filename = self.__prepare_filename(filename_template, lambda: str(item.video_url))
854 downloaded |= (not _already_downloaded(filename + ".mp4") and
855 self.download_pic(filename=filename, url=item.video_url, mtime=date_local))
640856 # Save caption if desired
641857 metadata_string = _ArbitraryItemFormatter(item).format(self.storyitem_metadata_txt_pattern).strip()
642858 if metadata_string:
718934 fast_update: bool = False,
719935 post_filter: Optional[Callable[[Post], bool]] = None,
720936 max_count: Optional[int] = None,
721 total_count: Optional[int] = None) -> None:
937 total_count: Optional[int] = None,
938 owner_profile: Optional[Profile] = None,
939 takewhile: Optional[Callable[[Post], bool]] = None) -> None:
722940 """
723941 Download the Posts returned by given Post Iterator.
724942
725 ..versionadded:: 4.4
943 .. versionadded:: 4.4
944
945 .. versionchanged:: 4.5
946 Transparently resume an aborted operation if `posts` is a :class:`NodeIterator`.
947
948 .. versionchanged:: 4.8
949 Add `takewhile` parameter.
726950
727951 :param posts: Post Iterator to loop through.
728 :param target: Target name
729 :param fast_update: :option:`--fast-update`
730 :param post_filter: :option:`--post-filter`
731 :param max_count: Maximum count of Posts to download (:option:`--count`)
732 :param total_count: Total number of posts returned by given iterator
733 """
734 for number, post in enumerate(posts):
735 if max_count is not None and number >= max_count:
736 break
737 if total_count is not None:
738 self.context.log("[{0:{w}d}/{1:{w}d}] ".format(number + 1, total_count,
739 w=len(str(total_count))),
740 end="", flush=True)
741 else:
742 if max_count is not None:
743 self.context.log("[{0:{w}d}/{1:{w}d}] ".format(number + 1, max_count,
744 w=len(str(max_count))),
952 :param target: Target name.
953 :param fast_update: :option:`--fast-update`.
954 :param post_filter: :option:`--post-filter`.
955 :param max_count: Maximum count of Posts to download (:option:`--count`).
956 :param total_count: Total number of posts returned by given iterator.
957 :param owner_profile: Associated profile, if any.
958 :param takewhile: Expression evaluated for each post. Once it returns false, downloading stops.
959 """
960 displayed_count = (max_count if total_count is None or max_count is not None and max_count < total_count
961 else total_count)
962 sanitized_target = target
963 if isinstance(target, str):
964 sanitized_target = _PostPathFormatter.sanitize_path(target)
965 if takewhile is None:
966 takewhile = lambda _: True
967 with resumable_iteration(
968 context=self.context,
969 iterator=posts,
970 load=load_structure_from_file,
971 save=save_structure_to_file,
972 format_path=lambda magic: self.format_filename_within_target_path(
973 sanitized_target, owner_profile, self.resume_prefix or '', magic, 'json.xz'
974 ),
975 check_bbd=self.check_resume_bbd,
976 enabled=self.resume_prefix is not None
977 ) as (is_resuming, start_index):
978 for number, post in enumerate(posts, start=start_index + 1):
979 if (max_count is not None and number > max_count) or not takewhile(post):
980 break
981 if displayed_count is not None:
982 self.context.log("[{0:{w}d}/{1:{w}d}] ".format(number, displayed_count,
983 w=len(str(displayed_count))),
745984 end="", flush=True)
746985 else:
747 self.context.log("[{:3d}] ".format(number + 1), end="", flush=True)
748 if post_filter is not None:
749 try:
750 if not post_filter(post):
751 self.context.log("{} skipped".format(post))
986 self.context.log("[{:3d}] ".format(number), end="", flush=True)
987 if post_filter is not None:
988 try:
989 if not post_filter(post):
990 self.context.log("{} skipped".format(post))
991 continue
992 except (InstaloaderException, KeyError, TypeError) as err:
993 self.context.error("{} skipped. Filter evaluation failed: {}".format(post, err))
752994 continue
753 except (InstaloaderException, KeyError, TypeError) as err:
754 self.context.error("{} skipped. Filter evaluation failed: {}".format(post, err))
755 continue
756 with self.context.error_catcher("Download {} of {}".format(post, target)):
757 # The PostChangedException gets raised if the Post's id/shortcode changed while obtaining
758 # additional metadata. This is most likely the case if a HTTP redirect takes place while
759 # resolving the shortcode URL.
760 # The `post_changed` variable keeps the fast-update functionality alive: A Post which is
761 # obained after a redirect has probably already been downloaded as a previous Post of the
762 # same Profile.
763 # Observed in issue #225: https://github.com/instaloader/instaloader/issues/225
764 post_changed = False
765 while True:
766 try:
767 downloaded = self.download_post(post, target=target)
768 break
769 except PostChangedException:
770 post_changed = True
771 continue
772 if fast_update and not downloaded and not post_changed:
773 break
995 with self.context.error_catcher("Download {} of {}".format(post, target)):
996 # The PostChangedException gets raised if the Post's id/shortcode changed while obtaining
997 # additional metadata. This is most likely the case if a HTTP redirect takes place while
998 # resolving the shortcode URL.
999 # The `post_changed` variable keeps the fast-update functionality alive: A Post which is
1000 # obained after a redirect has probably already been downloaded as a previous Post of the
1001 # same Profile.
1002 # Observed in issue #225: https://github.com/instaloader/instaloader/issues/225
1003 post_changed = False
1004 while True:
1005 try:
1006 downloaded = self.download_post(post, target=target)
1007 break
1008 except PostChangedException:
1009 post_changed = True
1010 continue
1011 if fast_update and not downloaded and not post_changed:
1012 # disengage fast_update for first post when resuming
1013 if not is_resuming or number > 0:
1014 break
7741015
7751016 @_requires_login
7761017 def get_feed_posts(self) -> Iterator[Post]:
8301071 """
8311072 self.context.log("Retrieving saved posts...")
8321073 assert self.context.username is not None # safe due to @_requires_login; required by typechecker
833 self.posts_download_loop(Profile.from_username(self.context, self.context.username).get_saved_posts(), ":saved",
834 fast_update, post_filter, max_count=max_count)
1074 node_iterator = Profile.own_profile(self.context).get_saved_posts()
1075 self.posts_download_loop(node_iterator, ":saved",
1076 fast_update, post_filter,
1077 max_count=max_count, total_count=node_iterator.count)
8351078
8361079 @_requires_login
8371080 def get_location_posts(self, location: str) -> Iterator[Post]:
8451088 .. versionchanged:: 4.2.9
8461089 Require being logged in (as required by Instagram)
8471090 """
848 has_next_page = True
849 end_cursor = None
850 while has_next_page:
851 if end_cursor:
852 params = {'__a': 1, 'max_id': end_cursor}
853 else:
854 params = {'__a': 1}
855 location_data = self.context.get_json('explore/locations/{0}/'.format(location),
856 params)['graphql']['location']['edge_location_to_media']
857 yield from (Post(self.context, edge['node']) for edge in location_data['edges'])
858 has_next_page = location_data['page_info']['has_next_page']
859 end_cursor = location_data['page_info']['end_cursor']
1091 yield from SectionIterator(
1092 self.context,
1093 lambda d: d["native_location_data"]["recent"],
1094 lambda m: Post.from_iphone_struct(self.context, m),
1095 f"explore/locations/{location}/",
1096 )
8601097
8611098 @_requires_login
8621099 def download_location(self, location: str,
8861123 max_count=max_count)
8871124
8881125 @_requires_login
889 def get_explore_posts(self) -> Iterator[Post]:
1126 def get_explore_posts(self) -> NodeIterator[Post]:
8901127 """Get Posts which are worthy of exploring suggested by Instagram.
8911128
8921129 :return: Iterator over Posts of the user's suggested posts.
1130 :rtype: NodeIterator[Post]
8931131 :raises LoginRequiredException: If called without being logged in.
8941132 """
895 data = self.context.get_json('explore/', {})
896 yield from (Post(self.context, node)
897 for node in self.context.graphql_node_list("df0dcc250c2b18d9fd27c5581ef33c7c",
898 {}, 'https://www.instagram.com/explore/',
899 lambda d: d['data']['user']['edge_web_discover_media'],
900 data.get('rhx_gis')))
1133 return NodeIterator(
1134 self.context,
1135 'df0dcc250c2b18d9fd27c5581ef33c7c',
1136 lambda d: d['data']['user']['edge_web_discover_media'],
1137 lambda n: Post(self.context, n),
1138 query_referer='https://www.instagram.com/explore/',
1139 )
9011140
9021141 def get_hashtag_posts(self, hashtag: str) -> Iterator[Post]:
9031142 """Get Posts associated with a #hashtag.
9501189
9511190 def download_tagged(self, profile: Profile, fast_update: bool = False,
9521191 target: Optional[str] = None,
953 post_filter: Optional[Callable[[Post], bool]] = None) -> None:
1192 post_filter: Optional[Callable[[Post], bool]] = None,
1193 latest_stamps: Optional[LatestStamps] = None) -> None:
9541194 """Download all posts where a profile is tagged.
9551195
956 .. versionadded:: 4.1"""
1196 .. versionadded:: 4.1
1197
1198 .. versionchanged:: 4.8
1199 Add `latest_stamps` parameter."""
9571200 self.context.log("Retrieving tagged posts for profile {}.".format(profile.username))
958 self.posts_download_loop(profile.get_tagged_posts(),
1201 posts_takewhile: Optional[Callable[[Post], bool]] = None
1202 if latest_stamps is not None:
1203 last_scraped = latest_stamps.get_last_tagged_timestamp(profile.username)
1204 posts_takewhile = lambda p: p.date_utc.replace(tzinfo=timezone.utc) > last_scraped
1205 tagged_posts = profile.get_tagged_posts()
1206 self.posts_download_loop(tagged_posts,
9591207 target if target
9601208 else (Path(_PostPathFormatter.sanitize_path(profile.username)) /
9611209 _PostPathFormatter.sanitize_path(':tagged')),
962 fast_update, post_filter)
1210 fast_update, post_filter, takewhile=posts_takewhile)
1211 if latest_stamps is not None and tagged_posts.first_item is not None:
1212 latest_stamps.set_last_tagged_timestamp(profile.username, tagged_posts.first_item.date_local.astimezone())
9631213
9641214 def download_igtv(self, profile: Profile, fast_update: bool = False,
965 post_filter: Optional[Callable[[Post], bool]] = None) -> None:
1215 post_filter: Optional[Callable[[Post], bool]] = None,
1216 latest_stamps: Optional[LatestStamps] = None) -> None:
9661217 """Download IGTV videos of a profile.
9671218
968 .. versionadded:: 4.3"""
1219 .. versionadded:: 4.3
1220
1221 .. versionchanged:: 4.8
1222 Add `latest_stamps` parameter."""
9691223 self.context.log("Retrieving IGTV videos for profile {}.".format(profile.username))
970 self.posts_download_loop(profile.get_igtv_posts(), profile.username, fast_update, post_filter,
971 total_count=profile.igtvcount)
1224 posts_takewhile: Optional[Callable[[Post], bool]] = None
1225 if latest_stamps is not None:
1226 last_scraped = latest_stamps.get_last_igtv_timestamp(profile.username)
1227 posts_takewhile = lambda p: p.date_utc.replace(tzinfo=timezone.utc) > last_scraped
1228 igtv_posts = profile.get_igtv_posts()
1229 self.posts_download_loop(igtv_posts, profile.username, fast_update, post_filter,
1230 total_count=profile.igtvcount, owner_profile=profile, takewhile=posts_takewhile)
1231 if latest_stamps is not None and igtv_posts.first_item is not None:
1232 latest_stamps.set_last_igtv_timestamp(profile.username, igtv_posts.first_item.date_local.astimezone())
9721233
9731234 def _get_id_filename(self, profile_name: str) -> str:
9741235 if ((format_string_contains_key(self.dirname_pattern, 'profile') or
9801241 return os.path.join(self.dirname_pattern.format(),
9811242 '{0}_id'.format(profile_name.lower()))
9821243
1244 def load_profile_id(self, profile_name: str) -> Optional[int]:
1245 """
1246 Load ID of profile from profile directory.
1247
1248 .. versionadded:: 4.8
1249 """
1250 id_filename = self._get_id_filename(profile_name)
1251 try:
1252 with open(id_filename, 'rb') as id_file:
1253 return int(id_file.read())
1254 except (FileNotFoundError, ValueError):
1255 return None
1256
9831257 def save_profile_id(self, profile: Profile):
9841258 """
985 Store ID of profile locally.
1259 Store ID of profile on profile directory.
9861260
9871261 .. versionadded:: 4.0.6
9881262 """
9921266 text_file.write(str(profile.userid) + "\n")
9931267 self.context.log("Stored ID {0} for profile {1}.".format(profile.userid, profile.username))
9941268
995 def check_profile_id(self, profile_name: str) -> Profile:
1269 def check_profile_id(self, profile_name: str, latest_stamps: Optional[LatestStamps] = None) -> Profile:
9961270 """
9971271 Consult locally stored ID of profile with given name, check whether ID matches and whether name
9981272 has changed and return current name of the profile, and store ID of profile.
9991273
10001274 :param profile_name: Profile name
1275 :param latest_stamps: Database of downloaded data. If present, IDs are retrieved from it,
1276 otherwise from the target directory
10011277 :return: Instance of current profile
1278
1279 .. versionchanged:: 4.8
1280 Add `latest_stamps` parameter.
10021281 """
10031282 profile = None
10041283 profile_name_not_exists_err = None
10061285 profile = Profile.from_username(self.context, profile_name)
10071286 except ProfileNotExistsException as err:
10081287 profile_name_not_exists_err = err
1009 id_filename = self._get_id_filename(profile_name)
1010 try:
1011 with open(id_filename, 'rb') as id_file:
1012 profile_id = int(id_file.read())
1288 if latest_stamps is None:
1289 profile_id = self.load_profile_id(profile_name)
1290 else:
1291 profile_id = latest_stamps.get_profile_id(profile_name)
1292 if profile_id is not None:
10131293 if (profile is None) or \
10141294 (profile_id != profile.userid):
10151295 if profile is not None:
10201300 profile_id))
10211301 profile_from_id = Profile.from_id(self.context, profile_id)
10221302 newname = profile_from_id.username
1023 self.context.log("Profile {0} has changed its name to {1}.".format(profile_name, newname))
1024 if ((format_string_contains_key(self.dirname_pattern, 'profile') or
1025 format_string_contains_key(self.dirname_pattern, 'target'))):
1026 os.rename(self.dirname_pattern.format(profile=profile_name.lower(),
1027 target=profile_name.lower()),
1028 self.dirname_pattern.format(profile=newname.lower(),
1029 target=newname.lower()))
1303 self.context.error("Profile {0} has changed its name to {1}.".format(profile_name, newname))
1304 if latest_stamps is None:
1305 if ((format_string_contains_key(self.dirname_pattern, 'profile') or
1306 format_string_contains_key(self.dirname_pattern, 'target'))):
1307 os.rename(self.dirname_pattern.format(profile=profile_name.lower(),
1308 target=profile_name.lower()),
1309 self.dirname_pattern.format(profile=newname.lower(),
1310 target=newname.lower()))
1311 else:
1312 os.rename('{0}/{1}_id'.format(self.dirname_pattern.format(), profile_name.lower()),
1313 '{0}/{1}_id'.format(self.dirname_pattern.format(), newname.lower()))
10301314 else:
1031 os.rename('{0}/{1}_id'.format(self.dirname_pattern.format(), profile_name.lower()),
1032 '{0}/{1}_id'.format(self.dirname_pattern.format(), newname.lower()))
1315 latest_stamps.rename_profile(profile_name, newname)
10331316 return profile_from_id
10341317 # profile exists and profile id matches saved id
10351318 return profile
1036 except (FileNotFoundError, ValueError):
1037 pass
10381319 if profile is not None:
1039 self.save_profile_id(profile)
1320 if latest_stamps is None:
1321 self.save_profile_id(profile)
1322 else:
1323 latest_stamps.save_profile_id(profile.username, profile.userid)
10401324 return profile
10411325 if profile_name_not_exists_err:
10421326 raise profile_name_not_exists_err
10511335 fast_update: bool = False,
10521336 post_filter: Optional[Callable[[Post], bool]] = None,
10531337 storyitem_filter: Optional[Callable[[Post], bool]] = None,
1054 raise_errors: bool = False):
1338 raise_errors: bool = False,
1339 latest_stamps: Optional[LatestStamps] = None):
10551340 """High-level method to download set of profiles.
10561341
10571342 :param profiles: Set of profiles to download.
10671352 :param raise_errors:
10681353 Whether :exc:`LoginRequiredException` and :exc:`PrivateProfileNotFollowedException` should be raised or
10691354 catched and printed with :meth:`InstaloaderContext.error_catcher`.
1355 :param latest_stamps: :option:`--latest-stamps`.
10701356
10711357 .. versionadded:: 4.1
10721358
10731359 .. versionchanged:: 4.3
10741360 Add `igtv` parameter.
1361
1362 .. versionchanged:: 4.8
1363 Add `latest_stamps` parameter.
10751364 """
10761365
10771366 @contextmanager
10781367 def _error_raiser(_str):
10791368 yield
10801369
1081 # error_handler type is Callable[[Optional[str]], ContextManager[None]] (not supported with Python 3.5)
1370 # error_handler type is Callable[[Optional[str]], ContextManager[None]] (not supported with Python 3.5.0..3.5.3)
10821371 error_handler = _error_raiser if raise_errors else self.context.error_catcher
10831372
1084 for profile in profiles:
1085 with error_handler(profile.username): # type: ignore
1373 for i, profile in enumerate(profiles, start=1):
1374 self.context.log("[{0:{w}d}/{1:{w}d}] Downloading profile {2}".format(i, len(profiles), profile.username,
1375 w=len(str(len(profiles)))))
1376 with error_handler(profile.username): # type: ignore # (ignore type for Python 3.5 support)
10861377 profile_name = profile.username
10871378
10881379 # Download profile picture
10891380 if profile_pic:
10901381 with self.context.error_catcher('Download profile picture of {}'.format(profile_name)):
1091 self.download_profilepic(profile)
1382 self.download_profilepic_if_new(profile, latest_stamps)
10921383
10931384 # Save metadata as JSON if desired.
10941385 if self.save_metadata:
10981389 self.save_metadata_json(json_filename, profile)
10991390
11001391 # Catch some errors
1101 if profile.is_private and (tagged or igtv or highlights or posts):
1102 if not self.context.is_logged_in:
1392 if tagged or igtv or highlights or posts:
1393 if (not self.context.is_logged_in and
1394 profile.is_private):
11031395 raise LoginRequiredException("--login=USERNAME required.")
1104 if not profile.followed_by_viewer and self.context.username != profile.username:
1396 if (self.context.username != profile.username and
1397 profile.is_private and
1398 not profile.followed_by_viewer):
11051399 raise PrivateProfileNotFollowedException("Private but not followed.")
11061400
11071401 # Download tagged, if requested
11081402 if tagged:
11091403 with self.context.error_catcher('Download tagged of {}'.format(profile_name)):
1110 self.download_tagged(profile, fast_update=fast_update, post_filter=post_filter)
1404 self.download_tagged(profile, fast_update=fast_update, post_filter=post_filter,
1405 latest_stamps=latest_stamps)
11111406
11121407 # Download IGTV, if requested
11131408 if igtv:
11141409 with self.context.error_catcher('Download IGTV of {}'.format(profile_name)):
1115 self.download_igtv(profile, fast_update=fast_update, post_filter=post_filter)
1410 self.download_igtv(profile, fast_update=fast_update, post_filter=post_filter,
1411 latest_stamps=latest_stamps)
11161412
11171413 # Download highlights, if requested
11181414 if highlights:
11221418 # Iterate over pictures and download them
11231419 if posts:
11241420 self.context.log("Retrieving posts from profile {}.".format(profile_name))
1125 self.posts_download_loop(profile.get_posts(), profile_name, fast_update, post_filter,
1126 total_count=profile.mediacount)
1421 posts_takewhile: Optional[Callable[[Post], bool]] = None
1422 if latest_stamps is not None:
1423 # pylint:disable=cell-var-from-loop
1424 last_scraped = latest_stamps.get_last_post_timestamp(profile_name)
1425 posts_takewhile = lambda p: p.date_utc.replace(tzinfo=timezone.utc) > last_scraped
1426 posts_to_download = profile.get_posts()
1427 self.posts_download_loop(posts_to_download, profile_name, fast_update, post_filter,
1428 total_count=profile.mediacount, owner_profile=profile,
1429 takewhile=posts_takewhile)
1430 if latest_stamps is not None and posts_to_download.first_item is not None:
1431 latest_stamps.set_last_post_timestamp(profile_name,
1432 posts_to_download.first_item.date_local.astimezone())
11271433
11281434 if stories and profiles:
11291435 with self.context.error_catcher("Download stories"):
11301436 self.context.log("Downloading stories")
11311437 self.download_stories(userids=list(profiles), fast_update=fast_update, filename_target=None,
1132 storyitem_filter=storyitem_filter)
1438 storyitem_filter=storyitem_filter, latest_stamps=latest_stamps)
11331439
11341440 def download_profile(self, profile_name: Union[str, Profile],
11351441 profile_pic: bool = True, profile_pic_only: bool = False,
12031509 # Iterate over pictures and download them
12041510 self.context.log("Retrieving posts from profile {}.".format(profile_name))
12051511 self.posts_download_loop(profile.get_posts(), profile_name, fast_update, post_filter,
1206 total_count=profile.mediacount)
1207
1208 def check_if_committed(self, filename: str) -> bool:
1209 """Checks to see if the current post has been committed.
1210
1211 A post is considered committed if its json metadata file exists and is not malformed.
1212
1213 .. versionadded:: 4.2
1214 """
1215 if os.path.isfile(filename + '.json.xz'):
1216 filename += '.json.xz'
1217 elif os.path.isfile(filename + '.json'):
1218 filename += '.json'
1219 else:
1220 return False
1221 try:
1222 load_structure_from_file(self.context, filename)
1223 return True
1224 except (FileNotFoundError, lzma.LZMAError, json.decoder.JSONDecodeError):
1225 return False
1512 total_count=profile.mediacount, owner_profile=profile)
12261513
12271514 def interactive_login(self, username: str) -> None:
12281515 """Logs in and internally stores session, asking user for password interactively.
12471534 code = input("Enter 2FA verification code: ")
12481535 self.two_factor_login(code)
12491536 break
1250 except BadCredentialsException:
1537 except BadCredentialsException as err:
1538 print(err, file=sys.stderr)
12511539 pass
00 import hashlib
11 import json
2 import os
23 import pickle
34 import random
45 import re
2223 """Duplicates a requests.Session."""
2324 new = requests.Session()
2425 new.cookies = requests.utils.cookiejar_from_dict(requests.utils.dict_from_cookiejar(session.cookies))
25 new.headers = session.headers.copy() # type: ignore
26 if request_timeout is not None:
27 # Override default timeout behavior.
28 # Need to silence mypy bug for this. See: https://github.com/python/mypy/issues/2427
29 new.request = partial(new.request, timeout=request_timeout) # type: ignore
26 new.headers = session.headers.copy()
27 # Override default timeout behavior.
28 # Need to silence mypy bug for this. See: https://github.com/python/mypy/issues/2427
29 new.request = partial(new.request, timeout=request_timeout) # type: ignore
3030 return new
3131
3232
3333 def default_user_agent() -> str:
3434 return 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 ' \
35 '(KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36'
35 '(KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36'
3636
3737
3838 class InstaloaderContext:
5151 """
5252
5353 def __init__(self, sleep: bool = True, quiet: bool = False, user_agent: Optional[str] = None,
54 max_connection_attempts: int = 3, request_timeout: Optional[float] = None):
54 max_connection_attempts: int = 3, request_timeout: float = 300.0,
55 rate_controller: Optional[Callable[["InstaloaderContext"], "RateController"]] = None,
56 fatal_status_codes: Optional[List[int]] = None,
57 iphone_support: bool = True):
5558
5659 self.user_agent = user_agent if user_agent is not None else default_user_agent()
5760 self.request_timeout = request_timeout
6366 self._graphql_page_length = 50
6467 self._root_rhx_gis = None
6568 self.two_factor_auth_pending = None
69 self.iphone_support = iphone_support
6670
6771 # error log, filled with error() and printed at the end of Instaloader.main()
6872 self.error_log = [] # type: List[str]
6973
70 # For the adaption of sleep intervals (rate control)
71 self._graphql_query_timestamps = dict() # type: Dict[str, List[float]]
72 self._graphql_earliest_next_request_time = 0.0
74 self._rate_controller = rate_controller(self) if rate_controller is not None else RateController(self)
7375
7476 # Can be set to True for testing, disables supression of InstaloaderContext._error_catcher
7577 self.raise_all_errors = False
78
79 # HTTP status codes that should cause an AbortDownloadException
80 self.fatal_status_codes = fatal_status_codes or []
7681
7782 # Cache profile from id (mapping from id to Profile)
7883 self.profile_id_cache = dict() # type: Dict[int, Any]
148153 if empty_session_only:
149154 del header['Host']
150155 del header['Origin']
151 del header['Referer']
152156 del header['X-Instagram-AJAX']
153157 del header['X-Requested-With']
154158 return header
160164 'ig_vw': '1920', 'csrftoken': '',
161165 's_network': '', 'ds_user_id': ''})
162166 session.headers.update(self._default_http_header(empty_session_only=True))
163 if self.request_timeout is not None:
164 # Override default timeout behavior.
165 # Need to silence mypy bug for this. See: https://github.com/python/mypy/issues/2427
166 session.request = partial(session.request, timeout=self.request_timeout) # type: ignore
167 # Override default timeout behavior.
168 # Need to silence mypy bug for this. See: https://github.com/python/mypy/issues/2427
169 session.request = partial(session.request, timeout=self.request_timeout) # type: ignore
167170 return session
168171
169172 def save_session_to_file(self, sessionfile):
176179 session.cookies = requests.utils.cookiejar_from_dict(pickle.load(sessionfile))
177180 session.headers.update(self._default_http_header())
178181 session.headers.update({'X-CSRFToken': session.cookies.get_dict()['csrftoken']})
179 if self.request_timeout is not None:
180 # Override default timeout behavior.
181 # Need to silence mypy bug for this. See: https://github.com/python/mypy/issues/2427
182 session.request = partial(session.request, timeout=self.request_timeout) # type: ignore
182 # Override default timeout behavior.
183 # Need to silence mypy bug for this. See: https://github.com/python/mypy/issues/2427
184 session.request = partial(session.request, timeout=self.request_timeout) # type: ignore
183185 self._session = session
184186 self.username = username
185187
205207 'ig_vw': '1920', 'ig_cb': '1', 'csrftoken': '',
206208 's_network': '', 'ds_user_id': ''})
207209 session.headers.update(self._default_http_header())
208 if self.request_timeout is not None:
209 # Override default timeout behavior.
210 # Need to silence mypy bug for this. See: https://github.com/python/mypy/issues/2427
211 session.request = partial(session.request, timeout=self.request_timeout) # type: ignore
212 session.get('https://www.instagram.com/web/__mid/')
213 csrf_token = session.cookies.get_dict()['csrftoken']
210 # Override default timeout behavior.
211 # Need to silence mypy bug for this. See: https://github.com/python/mypy/issues/2427
212 session.request = partial(session.request, timeout=self.request_timeout) # type: ignore
213 csrf_json = self.get_json('accounts/login/', {}, session=session)
214 csrf_token = csrf_json['config']['csrf_token']
214215 session.headers.update({'X-CSRFToken': csrf_token})
215216 # Not using self.get_json() here, because we need to access csrftoken cookie
216217 self.do_sleep()
221222 data={'enc_password': enc_password, 'username': user}, allow_redirects=True)
222223 try:
223224 resp_json = login.json()
224 except json.decoder.JSONDecodeError:
225 raise ConnectionException("Login error: JSON decode fail, {} - {}.".format(login.status_code, login.reason))
225 except json.decoder.JSONDecodeError as err:
226 raise ConnectionException(
227 "Login error: JSON decode fail, {} - {}.".format(login.status_code, login.reason)
228 ) from err
226229 if resp_json.get('two_factor_required'):
227230 two_factor_session = copy_session(session, self.request_timeout)
228231 two_factor_session.headers.update({'X-CSRFToken': csrf_token})
280283 resp_json = login.json()
281284 if resp_json['status'] != 'ok':
282285 if 'message' in resp_json:
283 raise BadCredentialsException("Login error: {}".format(resp_json['message']))
284 else:
285 raise BadCredentialsException("Login error: \"{}\" status.".format(resp_json['status']))
286 raise BadCredentialsException("2FA error: {}".format(resp_json['message']))
287 else:
288 raise BadCredentialsException("2FA error: \"{}\" status.".format(resp_json['status']))
286289 session.headers.update({'X-CSRFToken': login.cookies['csrftoken']})
287290 self._session = session
288291 self.username = user
291294 def do_sleep(self):
292295 """Sleep a short time if self.sleep is set. Called before each request to instagram.com."""
293296 if self.sleep:
294 time.sleep(min(random.expovariate(0.7), 5.0))
295
296 def _dump_query_timestamps(self, current_time: float):
297 """Output the number of GraphQL queries grouped by their query_hash within the last time."""
298 windows = [10, 11, 15, 20, 30, 60]
299 print("GraphQL requests:", file=sys.stderr)
300 for query_hash, times in self._graphql_query_timestamps.items():
301 print(" {}".format(query_hash), file=sys.stderr)
302 for window in windows:
303 reqs_in_sliding_window = sum(t > current_time - window * 60 for t in times)
304 print(" last {} minutes: {} requests".format(window, reqs_in_sliding_window), file=sys.stderr)
305
306 def _graphql_request_count_per_sliding_window(self, query_hash: str) -> int:
307 """Return how many GraphQL requests can be done within the sliding window."""
308 if self.is_logged_in:
309 max_reqs = {'1cb6ec562846122743b61e492c85999f': 20,
310 '33ba35852cb50da46f5b5e889df7d159': 20,
311 'iphone': 100,
312 'other': 100}
313 else:
314 max_reqs = {'1cb6ec562846122743b61e492c85999f': 200,
315 '33ba35852cb50da46f5b5e889df7d159': 200,
316 'other': 200}
317 return max_reqs.get(query_hash) or min(max_reqs.values())
318
319 def _graphql_query_waittime(self, query_hash: str, current_time: float, untracked_queries: bool = False) -> float:
320 """Calculate time needed to wait before GraphQL query can be executed."""
321 sliding_window = 660
322 if query_hash not in self._graphql_query_timestamps:
323 self._graphql_query_timestamps[query_hash] = []
324 self._graphql_query_timestamps[query_hash] = list(filter(lambda t: t > current_time - 60 * 60,
325 self._graphql_query_timestamps[query_hash]))
326 reqs_in_sliding_window = list(filter(lambda t: t > current_time - sliding_window,
327 self._graphql_query_timestamps[query_hash]))
328 count_per_sliding_window = self._graphql_request_count_per_sliding_window(query_hash)
329 if len(reqs_in_sliding_window) < count_per_sliding_window and not untracked_queries:
330 return max(0, self._graphql_earliest_next_request_time - current_time)
331 next_request_time = min(reqs_in_sliding_window) + sliding_window + 6
332 if untracked_queries:
333 self._graphql_earliest_next_request_time = next_request_time
334 return round(max(next_request_time, self._graphql_earliest_next_request_time) - current_time)
335
336 def _ratecontrol_graphql_query(self, query_hash: str, untracked_queries: bool = False):
337 """Called before a GraphQL query is made in order to stay within Instagram's rate limits.
338
339 :param query_hash: The query_hash parameter of the query.
340 :param untracked_queries: True, if 429 has been returned to apply 429 logic.
341 """
342 if not untracked_queries:
343 waittime = self._graphql_query_waittime(query_hash, time.monotonic(), untracked_queries)
344 assert waittime >= 0
345 if waittime > 10:
346 self.log('\nToo many queries in the last time. Need to wait {} seconds, until {:%H:%M}.'
347 .format(waittime, datetime.now() + timedelta(seconds=waittime)))
348 time.sleep(waittime)
349 if query_hash not in self._graphql_query_timestamps:
350 self._graphql_query_timestamps[query_hash] = [time.monotonic()]
351 else:
352 self._graphql_query_timestamps[query_hash].append(time.monotonic())
353 else:
354 text_for_429 = ("HTTP error code 429 was returned because too many queries occurred in the last time. "
355 "Please do not use Instagram in your browser or run multiple instances of Instaloader "
356 "in parallel.")
357 print(textwrap.fill(text_for_429), file=sys.stderr)
358 current_time = time.monotonic()
359 waittime = self._graphql_query_waittime(query_hash, current_time, untracked_queries)
360 assert waittime >= 0
361 if waittime > 10:
362 self.log('The request will be retried in {} seconds, at {:%H:%M}.'
363 .format(waittime, datetime.now() + timedelta(seconds=waittime)))
364 self._dump_query_timestamps(current_time)
365 time.sleep(waittime)
297 time.sleep(min(random.expovariate(0.6), 15.0))
366298
367299 def get_json(self, path: str, params: Dict[str, Any], host: str = 'www.instagram.com',
368300 session: Optional[requests.Session] = None, _attempt=1) -> Dict[str, Any]:
384316 try:
385317 self.do_sleep()
386318 if is_graphql_query:
387 self._ratecontrol_graphql_query(params['query_hash'])
319 self._rate_controller.wait_before_query(params['query_hash'])
388320 if is_iphone_query:
389 self._ratecontrol_graphql_query('iphone')
321 self._rate_controller.wait_before_query('iphone')
390322 if is_other_query:
391 self._ratecontrol_graphql_query('other')
323 self._rate_controller.wait_before_query('other')
392324 resp = sess.get('https://{0}/{1}'.format(host, path), params=params, allow_redirects=False)
325 if resp.status_code in self.fatal_status_codes:
326 redirect = " redirect to {}".format(resp.headers['location']) if 'location' in resp.headers else ""
327 raise AbortDownloadException("Query to https://{}/{} responded with \"{} {}\"{}".format(
328 host, path, resp.status_code, resp.reason, redirect
329 ))
393330 while resp.is_redirect:
394331 redirect_url = resp.headers['location']
395332 self.log('\nHTTP redirect from https://{0}/{1} to {2}'.format(host, path, redirect_url))
396333 if redirect_url.startswith('https://www.instagram.com/accounts/login'):
334 if not self.is_logged_in:
335 raise LoginRequiredException("Redirected to login page. Use --login.")
397336 # alternate rate limit exceeded behavior
398 raise TooManyRequestsException("429 Too Many Requests: redirected to login")
337 raise TooManyRequestsException("Redirected to login")
399338 if redirect_url.startswith('https://{}/'.format(host)):
400339 resp = sess.get(redirect_url if redirect_url.endswith('/') else redirect_url + '/',
401340 params=params, allow_redirects=False)
421360 raise ConnectionException("\"window._sharedData\" does not contain required keys.")
422361 # If GraphQL data is missing in `window._sharedData`, search for it in `__additionalDataLoaded`.
423362 if 'graphql' not in post_or_profile_page[0]:
424 match = re.search(r'window\.__additionalDataLoaded\([^{]+{"graphql":({.*})}\);</script>',
363 match = re.search(r'window\.__additionalDataLoaded\(.*?({.*"graphql":.*})\);</script>',
425364 resp.text)
426365 if match is not None:
427 post_or_profile_page[0]['graphql'] = json.loads(match.group(1))
366 post_or_profile_page[0]['graphql'] = json.loads(match.group(1))['graphql']
428367 return resp_json
429368 else:
430369 resp_json = resp.json()
444383 raise ConnectionException(error_string) from err
445384 self.error(error_string + " [retrying; skip with ^C]", repeat_at_end=False)
446385 try:
447 if is_graphql_query and isinstance(err, TooManyRequestsException):
448 self._ratecontrol_graphql_query(params['query_hash'], untracked_queries=True)
449 if is_iphone_query and isinstance(err, TooManyRequestsException):
450 self._ratecontrol_graphql_query('iphone', untracked_queries=True)
451 if is_other_query and isinstance(err, TooManyRequestsException):
452 self._ratecontrol_graphql_query('other', untracked_queries=True)
386 if isinstance(err, TooManyRequestsException):
387 if is_graphql_query:
388 self._rate_controller.handle_429(params['query_hash'])
389 if is_iphone_query:
390 self._rate_controller.handle_429('iphone')
391 if is_other_query:
392 self._rate_controller.handle_429('other')
453393 return self.get_json(path=path, params=params, host=host, session=sess, _attempt=_attempt + 1)
454394 except KeyboardInterrupt:
455395 self.error("[skipped by user]", repeat_at_end=False)
497437 edge_extractor: Callable[[Dict[str, Any]], Dict[str, Any]],
498438 rhx_gis: Optional[str] = None,
499439 first_data: Optional[Dict[str, Any]] = None) -> Iterator[Dict[str, Any]]:
500 """Retrieve a list of GraphQL nodes."""
440 """
441 Retrieve a list of GraphQL nodes.
442
443 .. deprecated:: 4.5
444 Use :class:`NodeIterator` instead, which provides more functionality.
445 """
501446
502447 def _query():
503448 query_variables['first'] = self._graphql_page_length
535480
536481 .. versionadded:: 4.2.1"""
537482 with copy_session(self._session, self.request_timeout) as tempsession:
538 tempsession.headers['User-Agent'] = 'Instagram 123.1.0.26.115 (iPhone12,1; iOS 13_3; en_US; en-US; ' \
483 tempsession.headers['User-Agent'] = 'Instagram 146.0.0.27.125 (iPhone12,1; iOS 13_3; en_US; en-US; ' \
539484 'scale=2.00; 1656x3584; 190542906)'
540485 for header in ['Host', 'Origin', 'X-Instagram-AJAX', 'X-Requested-With']:
541486 tempsession.headers.pop(header, None)
546491
547492 .. versionadded:: 4.2.1"""
548493 self.log(filename, end=' ', flush=True)
549 with open(filename, 'wb') as file:
494 with open(filename + '.temp', 'wb') as file:
550495 if isinstance(resp, requests.Response):
551496 shutil.copyfileobj(resp.raw, file)
552497 else:
553498 file.write(resp)
499 os.replace(filename + '.temp', filename)
554500
555501 def get_raw(self, url: str, _attempt=1) -> requests.Response:
556502 """Downloads a file anonymously.
582528 :raises ConnectionException: When download repeatedly failed."""
583529 self.write_raw(self.get_raw(url), filename)
584530
531 def head(self, url: str, allow_redirects: bool = False) -> requests.Response:
532 """HEAD a URL anonymously.
533
534 :raises QueryReturnedNotFoundException: When the server responds with a 404.
535 :raises QueryReturnedForbiddenException: When the server responds with a 403.
536 :raises ConnectionException: When request failed.
537
538 .. versionadded:: 4.7.6
539 """
540 with self.get_anonymous_session() as anonymous_session:
541 resp = anonymous_session.head(url, allow_redirects=allow_redirects)
542 if resp.status_code == 200:
543 return resp
544 else:
545 if resp.status_code == 403:
546 # suspected invalid URL signature
547 raise QueryReturnedForbiddenException("403 when accessing {}.".format(url))
548 if resp.status_code == 404:
549 # 404 not worth retrying.
550 raise QueryReturnedNotFoundException("404 when accessing {}.".format(url))
551 raise ConnectionException("HTTP error code {}.".format(resp.status_code))
552
585553 @property
586554 def root_rhx_gis(self) -> Optional[str]:
587555 """rhx_gis string returned in the / query."""
592560 if self._root_rhx_gis is None:
593561 self._root_rhx_gis = self.get_json('', {}).get('rhx_gis', '')
594562 return self._root_rhx_gis or None
563
564
565 class RateController:
566 """
567 Class providing request tracking and rate controlling to stay within rate limits.
568
569 It can be overridden to change Instaloader's behavior regarding rate limits, for example to raise a custom
570 exception when the rate limit is hit::
571
572 import instaloader
573
574 class MyRateController(instaloader.RateController):
575 def sleep(self, secs):
576 raise MyCustomException()
577
578 L = instaloader.Instaloader(rate_controller=lambda ctx: MyRateController(ctx))
579 """
580
581 def __init__(self, context: InstaloaderContext):
582 self._context = context
583 self._query_timestamps = dict() # type: Dict[str, List[float]]
584 self._earliest_next_request_time = 0.0
585 self._iphone_earliest_next_request_time = 0.0
586
587 def sleep(self, secs: float):
588 """Wait given number of seconds."""
589 # Not static, to allow for the behavior of this method to depend on context-inherent properties, such as
590 # whether we are logged in.
591 # pylint:disable=no-self-use
592 time.sleep(secs)
593
594 def _dump_query_timestamps(self, current_time: float, failed_query_type: str):
595 windows = [10, 11, 20, 22, 30, 60]
596 self._context.error("Number of requests within last {} minutes grouped by type:"
597 .format('/'.join(str(w) for w in windows)),
598 repeat_at_end=False)
599 for query_type, times in self._query_timestamps.items():
600 reqs_in_sliding_window = [sum(t > current_time - w * 60 for t in times) for w in windows]
601 self._context.error(" {} {:>32}: {}".format(
602 "*" if query_type == failed_query_type else " ",
603 query_type,
604 " ".join("{:4}".format(reqs) for reqs in reqs_in_sliding_window)
605 ), repeat_at_end=False)
606
607 def count_per_sliding_window(self, query_type: str) -> int:
608 """Return how many requests of the given type can be done within a sliding window of 11 minutes.
609
610 This is called by :meth:`RateController.query_waittime` and allows to simply customize wait times before queries
611 at query_type granularity. Consider overriding :meth:`RateController.query_waittime` directly if you need more
612 control."""
613 # Not static, to allow for the count_per_sliding_window to depend on context-inherent properties, such as
614 # whether we are logged in.
615 # pylint:disable=no-self-use
616 return 75 if query_type == 'other' else 200
617
618 def _reqs_in_sliding_window(self, query_type: Optional[str], current_time: float, window: float) -> List[float]:
619 if query_type is not None:
620 # timestamps of type query_type
621 relevant_timestamps = self._query_timestamps[query_type]
622 else:
623 # all GraphQL queries, i.e. not 'iphone' or 'other'
624 graphql_query_timestamps = filter(lambda tp: tp[0] not in ['iphone', 'other'],
625 self._query_timestamps.items())
626 relevant_timestamps = [t for times in (tp[1] for tp in graphql_query_timestamps) for t in times]
627 return list(filter(lambda t: t > current_time - window, relevant_timestamps))
628
629 def query_waittime(self, query_type: str, current_time: float, untracked_queries: bool = False) -> float:
630 """Calculate time needed to wait before query can be executed."""
631 per_type_sliding_window = 660
632 iphone_sliding_window = 1800
633 if query_type not in self._query_timestamps:
634 self._query_timestamps[query_type] = []
635 self._query_timestamps[query_type] = list(filter(lambda t: t > current_time - 60 * 60,
636 self._query_timestamps[query_type]))
637
638 def per_type_next_request_time():
639 reqs_in_sliding_window = self._reqs_in_sliding_window(query_type, current_time, per_type_sliding_window)
640 if len(reqs_in_sliding_window) < self.count_per_sliding_window(query_type):
641 return 0.0
642 else:
643 return min(reqs_in_sliding_window) + per_type_sliding_window + 6
644
645 def gql_accumulated_next_request_time():
646 if query_type in ['iphone', 'other']:
647 return 0.0
648 gql_accumulated_sliding_window = 600
649 gql_accumulated_max_count = 275
650 reqs_in_sliding_window = self._reqs_in_sliding_window(None, current_time, gql_accumulated_sliding_window)
651 if len(reqs_in_sliding_window) < gql_accumulated_max_count:
652 return 0.0
653 else:
654 return min(reqs_in_sliding_window) + gql_accumulated_sliding_window
655
656 def untracked_next_request_time():
657 if untracked_queries:
658 if query_type == "iphone":
659 reqs_in_sliding_window = self._reqs_in_sliding_window(query_type, current_time,
660 iphone_sliding_window)
661 self._iphone_earliest_next_request_time = min(reqs_in_sliding_window) + iphone_sliding_window + 18
662 else:
663 reqs_in_sliding_window = self._reqs_in_sliding_window(query_type, current_time,
664 per_type_sliding_window)
665 self._earliest_next_request_time = min(reqs_in_sliding_window) + per_type_sliding_window + 6
666 return max(self._iphone_earliest_next_request_time, self._earliest_next_request_time)
667
668 def iphone_next_request():
669 if query_type == "iphone":
670 reqs_in_sliding_window = self._reqs_in_sliding_window(query_type, current_time, iphone_sliding_window)
671 if len(reqs_in_sliding_window) >= 199:
672 return min(reqs_in_sliding_window) + iphone_sliding_window + 18
673 return 0.0
674
675 return max(0.0,
676 max(
677 per_type_next_request_time(),
678 gql_accumulated_next_request_time(),
679 untracked_next_request_time(),
680 iphone_next_request(),
681 ) - current_time)
682
683 def wait_before_query(self, query_type: str) -> None:
684 """This method is called before a query to Instagram.
685
686 It calls :meth:`RateController.query_waittime` to determine the time needed to wait and then calls
687 :meth:`RateController.sleep` to wait until the request can be made."""
688 waittime = self.query_waittime(query_type, time.monotonic(), False)
689 assert waittime >= 0
690 if waittime > 15:
691 formatted_waittime = ("{} seconds".format(round(waittime)) if waittime <= 666 else
692 "{} minutes".format(round(waittime / 60)))
693 self._context.log("\nToo many queries in the last time. Need to wait {}, until {:%H:%M}."
694 .format(formatted_waittime, datetime.now() + timedelta(seconds=waittime)))
695 if waittime > 0:
696 self.sleep(waittime)
697 if query_type not in self._query_timestamps:
698 self._query_timestamps[query_type] = [time.monotonic()]
699 else:
700 self._query_timestamps[query_type].append(time.monotonic())
701
702 def handle_429(self, query_type: str) -> None:
703 """This method is called to handle a 429 Too Many Requests response.
704
705 It calls :meth:`RateController.query_waittime` to determine the time needed to wait and then calls
706 :meth:`RateController.sleep` to wait until we can repeat the same request."""
707 current_time = time.monotonic()
708 waittime = self.query_waittime(query_type, current_time, True)
709 assert waittime >= 0
710 self._dump_query_timestamps(current_time, query_type)
711 text_for_429 = ("Instagram responded with HTTP error \"429 - Too Many Requests\". Please do not run multiple "
712 "instances of Instaloader in parallel or within short sequence. Also, do not use any Instagram "
713 "App while Instaloader is running.")
714 self._context.error(textwrap.fill(text_for_429), repeat_at_end=False)
715 if waittime > 1.5:
716 formatted_waittime = ("{} seconds".format(round(waittime)) if waittime <= 666 else
717 "{} minutes".format(round(waittime / 60)))
718 self._context.error("The request will be retried in {}, at {:%H:%M}."
719 .format(formatted_waittime, datetime.now() + timedelta(seconds=waittime)),
720 repeat_at_end=False)
721 if waittime > 0:
722 self.sleep(waittime)
0 import configparser
1 from datetime import datetime, timezone
2 from typing import Optional
3
4
5 class LatestStamps:
6 """LatestStamps class.
7
8 Convenience class for retrieving and storing data from the :option:`--latest-stamps` file.
9
10 :param latest_stamps_file: path to file.
11
12 .. versionadded:: 4.8"""
13 PROFILE_ID = 'profile-id'
14 PROFILE_PIC = 'profile-pic'
15 POST_TIMESTAMP = 'post-timestamp'
16 TAGGED_TIMESTAMP = 'tagged-timestamp'
17 IGTV_TIMESTAMP = 'igtv-timestamp'
18 STORY_TIMESTAMP = 'story-timestamp'
19 ISO_FORMAT = '%Y-%m-%dT%H:%M:%S.%f%z'
20
21 def __init__(self, latest_stamps_file):
22 self.file = latest_stamps_file
23 self.data = configparser.ConfigParser()
24 self.data.read(latest_stamps_file)
25
26 def _save(self):
27 with open(self.file, 'w') as f:
28 self.data.write(f)
29
30 def _ensure_section(self, section: str):
31 if not self.data.has_section(section):
32 self.data.add_section(section)
33
34 def get_profile_id(self, profile_name: str) -> Optional[int]:
35 """Returns stored ID of profile."""
36 try:
37 return self.data.getint(profile_name, self.PROFILE_ID)
38 except (configparser.Error, ValueError):
39 return None
40
41 def save_profile_id(self, profile_name: str, profile_id: int):
42 """Stores ID of profile."""
43 self._ensure_section(profile_name)
44 self.data.set(profile_name, self.PROFILE_ID, str(profile_id))
45 self._save()
46
47 def rename_profile(self, old_profile: str, new_profile: str):
48 """Renames a profile."""
49 self._ensure_section(new_profile)
50 for option in [self.PROFILE_ID, self.PROFILE_PIC, self.POST_TIMESTAMP,
51 self.TAGGED_TIMESTAMP, self.IGTV_TIMESTAMP, self.STORY_TIMESTAMP]:
52 if self.data.has_option(old_profile, option):
53 value = self.data.get(old_profile, option)
54 self.data.set(new_profile, option, value)
55 self.data.remove_section(old_profile)
56 self._save()
57
58 def _get_timestamp(self, section: str, key: str) -> datetime:
59 try:
60 return datetime.strptime(self.data.get(section, key), self.ISO_FORMAT)
61 except (configparser.Error, ValueError):
62 return datetime.fromtimestamp(0, timezone.utc)
63
64 def _set_timestamp(self, section: str, key: str, timestamp: datetime):
65 self._ensure_section(section)
66 self.data.set(section, key, timestamp.strftime(self.ISO_FORMAT))
67 self._save()
68
69 def get_last_post_timestamp(self, profile_name: str) -> datetime:
70 """Returns timestamp of last download of a profile's posts."""
71 return self._get_timestamp(profile_name, self.POST_TIMESTAMP)
72
73 def set_last_post_timestamp(self, profile_name: str, timestamp: datetime):
74 """Sets timestamp of last download of a profile's posts."""
75 self._set_timestamp(profile_name, self.POST_TIMESTAMP, timestamp)
76
77 def get_last_tagged_timestamp(self, profile_name: str) -> datetime:
78 """Returns timestamp of last download of a profile's tagged posts."""
79 return self._get_timestamp(profile_name, self.TAGGED_TIMESTAMP)
80
81 def set_last_tagged_timestamp(self, profile_name: str, timestamp: datetime):
82 """Sets timestamp of last download of a profile's tagged posts."""
83 self._set_timestamp(profile_name, self.TAGGED_TIMESTAMP, timestamp)
84
85 def get_last_igtv_timestamp(self, profile_name: str) -> datetime:
86 """Returns timestamp of last download of a profile's igtv posts."""
87 return self._get_timestamp(profile_name, self.IGTV_TIMESTAMP)
88
89 def set_last_igtv_timestamp(self, profile_name: str, timestamp: datetime):
90 """Sets timestamp of last download of a profile's igtv posts."""
91 self._set_timestamp(profile_name, self.IGTV_TIMESTAMP, timestamp)
92
93 def get_last_story_timestamp(self, profile_name: str) -> datetime:
94 """Returns timestamp of last download of a profile's stories."""
95 return self._get_timestamp(profile_name, self.STORY_TIMESTAMP)
96
97 def set_last_story_timestamp(self, profile_name: str, timestamp: datetime):
98 """Sets timestamp of last download of a profile's stories."""
99 self._set_timestamp(profile_name, self.STORY_TIMESTAMP, timestamp)
100
101 def get_profile_pic(self, profile_name: str) -> str:
102 """Returns filename of profile's last downloaded profile pic."""
103 try:
104 return self.data.get(profile_name, self.PROFILE_PIC)
105 except configparser.Error:
106 return ""
107
108 def set_profile_pic(self, profile_name: str, profile_pic: str):
109 """Sets filename of profile's last downloaded profile pic."""
110 self._ensure_section(profile_name)
111 self.data.set(profile_name, self.PROFILE_PIC, profile_pic)
112 self._save()
0 import base64
1 import hashlib
2 import json
3 import os
4 from contextlib import contextmanager
5 from datetime import datetime, timedelta
6 from lzma import LZMAError
7 from typing import Any, Callable, Dict, Iterable, Iterator, NamedTuple, Optional, Tuple, TypeVar
8
9 from .exceptions import AbortDownloadException, InvalidArgumentException, QueryReturnedBadRequestException
10 from .instaloadercontext import InstaloaderContext
11
12 FrozenNodeIterator = NamedTuple('FrozenNodeIterator',
13 [('query_hash', str),
14 ('query_variables', Dict),
15 ('query_referer', Optional[str]),
16 ('context_username', Optional[str]),
17 ('total_index', int),
18 ('best_before', Optional[float]),
19 ('remaining_data', Optional[Dict]),
20 ('first_node', Optional[Dict])])
21 FrozenNodeIterator.query_hash.__doc__ = """The GraphQL ``query_hash`` parameter."""
22 FrozenNodeIterator.query_variables.__doc__ = """The GraphQL ``query_variables`` parameter."""
23 FrozenNodeIterator.query_referer.__doc__ = """The HTTP referer used for the GraphQL query."""
24 FrozenNodeIterator.context_username.__doc__ = """The username who created the iterator, or ``None``."""
25 FrozenNodeIterator.total_index.__doc__ = """Number of items that have already been returned."""
26 FrozenNodeIterator.best_before.__doc__ = """Date when parts of the stored nodes might have expired."""
27 FrozenNodeIterator.remaining_data.__doc__ = \
28 """The already-retrieved, yet-unprocessed ``edges`` and the ``page_info`` at time of freezing."""
29 FrozenNodeIterator.first_node.__doc__ = """Node data of the first item, if an item has been produced."""
30
31 T = TypeVar('T')
32
33
34 class NodeIterator(Iterator[T]):
35 """
36 Iterate the nodes within edges in a GraphQL pagination. Instances of this class are returned by many (but not all)
37 of Instaloader's :class:`Post`-returning functions (such as :meth:`Profile.get_posts` etc.).
38
39 What makes this iterator special is its ability to freeze/store its current state, e.g. to interrupt an iteration,
40 and later thaw/resume from where it left off.
41
42 You can freeze a NodeIterator with :meth:`NodeIterator.freeze`::
43
44 post_iterator = profile.get_posts()
45 try:
46 for post in post_iterator:
47 do_something_with(post)
48 except KeyboardInterrupt:
49 save("resume_information.json", post_iterator.freeze())
50
51 and later reuse it with :meth:`NodeIterator.thaw` on an equally-constructed NodeIterator::
52
53 post_iterator = profile.get_posts()
54 post_iterator.thaw(load("resume_information.json"))
55
56 (an appropriate method to load and save the :class:`FrozenNodeIterator` is e.g.
57 :func:`load_structure_from_file` and :func:`save_structure_to_file`.)
58
59 A :class:`FrozenNodeIterator` can only be thawn with a matching NodeIterator, i.e. a NodeIterator instance that has
60 been constructed with the same parameters as the instance that is represented by the :class:`FrozenNodeIterator` in
61 question. This is to ensure that an iteration cannot be resumed in a wrong, unmatching loop. As a quick way to
62 distinguish iterators that are saved e.g. in files, there is the :attr:`NodeIterator.magic` string: Two
63 NodeIterators are matching if and only if they have the same magic.
64
65 See also :func:`resumable_iteration` for a high-level context manager that handles a resumable iteration.
66 """
67
68 _graphql_page_length = 50
69 _shelf_life = timedelta(days=29)
70
71 def __init__(self,
72 context: InstaloaderContext,
73 query_hash: str,
74 edge_extractor: Callable[[Dict[str, Any]], Dict[str, Any]],
75 node_wrapper: Callable[[Dict], T],
76 query_variables: Optional[Dict[str, Any]] = None,
77 query_referer: Optional[str] = None,
78 first_data: Optional[Dict[str, Any]] = None):
79 self._context = context
80 self._query_hash = query_hash
81 self._edge_extractor = edge_extractor
82 self._node_wrapper = node_wrapper
83 self._query_variables = query_variables if query_variables is not None else {}
84 self._query_referer = query_referer
85 self._page_index = 0
86 self._total_index = 0
87 if first_data is not None:
88 self._data = first_data
89 self._best_before = datetime.now() + NodeIterator._shelf_life
90 else:
91 self._data = self._query()
92 self._first_node: Optional[Dict] = None
93
94 def _query(self, after: Optional[str] = None) -> Dict:
95 pagination_variables = {'first': NodeIterator._graphql_page_length} # type: Dict[str, Any]
96 if after is not None:
97 pagination_variables['after'] = after
98 try:
99 data = self._edge_extractor(
100 self._context.graphql_query(
101 self._query_hash, {**self._query_variables, **pagination_variables}, self._query_referer
102 )
103 )
104 self._best_before = datetime.now() + NodeIterator._shelf_life
105 return data
106 except QueryReturnedBadRequestException:
107 new_page_length = int(NodeIterator._graphql_page_length / 2)
108 if new_page_length >= 12:
109 NodeIterator._graphql_page_length = new_page_length
110 self._context.error("HTTP Error 400 (Bad Request) on GraphQL Query. Retrying with shorter page length.",
111 repeat_at_end=False)
112 return self._query(after)
113 else:
114 raise
115
116 def __iter__(self):
117 return self
118
119 def __next__(self) -> T:
120 if self._page_index < len(self._data['edges']):
121 node = self._data['edges'][self._page_index]['node']
122 page_index, total_index = self._page_index, self._total_index
123 try:
124 self._page_index += 1
125 self._total_index += 1
126 except KeyboardInterrupt:
127 self._page_index, self._total_index = page_index, total_index
128 raise
129 item = self._node_wrapper(node)
130 if self._first_node is None:
131 self._first_node = node
132 return item
133 if self._data['page_info']['has_next_page']:
134 query_response = self._query(self._data['page_info']['end_cursor'])
135 page_index, data = self._page_index, self._data
136 try:
137 self._page_index = 0
138 self._data = query_response
139 except KeyboardInterrupt:
140 self._page_index, self._data = page_index, data
141 raise
142 return self.__next__()
143 raise StopIteration()
144
145 @property
146 def count(self) -> Optional[int]:
147 """The ``count`` as returned by Instagram. This is not always the total count this iterator will yield."""
148 return self._data.get('count') if self._data is not None else None
149
150 @property
151 def total_index(self) -> int:
152 """Number of items that have already been returned."""
153 return self._total_index
154
155 @property
156 def magic(self) -> str:
157 """Magic string for easily identifying a matching iterator file for resuming (hash of some parameters)."""
158 magic_hash = hashlib.blake2b(digest_size=6)
159 magic_hash.update(json.dumps(
160 [self._query_hash, self._query_variables, self._query_referer, self._context.username]
161 ).encode())
162 return base64.urlsafe_b64encode(magic_hash.digest()).decode()
163
164 @property
165 def first_item(self) -> Optional[T]:
166 """
167 If this iterator has produced any items, returns the first item produced.
168
169 .. versionadded:: 4.8
170 """
171 return self._node_wrapper(self._first_node) if self._first_node is not None else None
172
173 def freeze(self) -> FrozenNodeIterator:
174 """Freeze the iterator for later resuming."""
175 remaining_data = None
176 if self._data is not None:
177 remaining_data = {**self._data,
178 'edges': (self._data['edges'][(max(self._page_index - 1, 0)):])}
179 return FrozenNodeIterator(
180 query_hash=self._query_hash,
181 query_variables=self._query_variables,
182 query_referer=self._query_referer,
183 context_username=self._context.username,
184 total_index=max(self.total_index - 1, 0),
185 best_before=self._best_before.timestamp() if self._best_before else None,
186 remaining_data=remaining_data,
187 first_node=self._first_node,
188 )
189
190 def thaw(self, frozen: FrozenNodeIterator) -> None:
191 """
192 Use this iterator for resuming from earlier iteration.
193
194 :raises InvalidArgumentException:
195 If
196
197 - the iterator on which this method is called has already been used, or
198 - the given :class:`FrozenNodeIterator` does not match, i.e. belongs to a different iteration.
199 """
200 if self._total_index or self._page_index:
201 raise InvalidArgumentException("thaw() called on already-used iterator.")
202 if (self._query_hash != frozen.query_hash or
203 self._query_variables != frozen.query_variables or
204 self._query_referer != frozen.query_referer or
205 self._context.username != frozen.context_username):
206 raise InvalidArgumentException("Mismatching resume information.")
207 if not frozen.best_before:
208 raise InvalidArgumentException("\"best before\" date missing.")
209 if frozen.remaining_data is None:
210 raise InvalidArgumentException("\"remaining_data\" missing.")
211 self._total_index = frozen.total_index
212 self._best_before = datetime.fromtimestamp(frozen.best_before)
213 self._data = frozen.remaining_data
214 if frozen.first_node is not None:
215 self._first_node = frozen.first_node
216
217
218 @contextmanager
219 def resumable_iteration(context: InstaloaderContext,
220 iterator: Iterable,
221 load: Callable[[InstaloaderContext, str], Any],
222 save: Callable[[FrozenNodeIterator, str], None],
223 format_path: Callable[[str], str],
224 check_bbd: bool = True,
225 enabled: bool = True) -> Iterator[Tuple[bool, int]]:
226 """
227 High-level context manager to handle a resumable iteration that can be interrupted
228 with a :class:`KeyboardInterrupt` or an :class:`AbortDownloadException`.
229
230 It can be used as follows to automatically load a previously-saved state into the iterator, save the iterator's
231 state when interrupted, and delete the resume file upon completion::
232
233 post_iterator = profile.get_posts()
234 with resumable_iteration(
235 context=L.context,
236 iterator=post_iterator,
237 load=lambda _, path: FrozenNodeIterator(**json.load(open(path))),
238 save=lambda fni, path: json.dump(fni._asdict(), open(path, 'w')),
239 format_path=lambda magic: "resume_info_{}.json".format(magic)
240 ) as (is_resuming, start_index):
241 for post in post_iterator:
242 do_something_with(post)
243
244 It yields a tuple (is_resuming, start_index).
245
246 When the passed iterator is not a :class:`NodeIterator`, it behaves as if ``resumable_iteration`` was not used,
247 just executing the inner body.
248
249 :param context: The :class:`InstaloaderContext`.
250 :param iterator: The fresh :class:`NodeIterator`.
251 :param load: Loads a FrozenNodeIterator from given path. The object is ignored if it has a different type.
252 :param save: Saves the given FrozenNodeIterator to the given path.
253 :param format_path: Returns the path to the resume file for the given magic.
254 :param check_bbd: Whether to check the best before date and reject an expired FrozenNodeIterator.
255 :param enabled: Set to False to disable all functionality and simply execute the inner body.
256
257 .. versionchanged:: 4.7
258 Also interrupt on :class:`AbortDownloadException`.
259 """
260 if not enabled or not isinstance(iterator, NodeIterator):
261 yield False, 0
262 return
263 is_resuming = False
264 start_index = 0
265 resume_file_path = format_path(iterator.magic)
266 resume_file_exists = os.path.isfile(resume_file_path)
267 if resume_file_exists:
268 try:
269 fni = load(context, resume_file_path)
270 if not isinstance(fni, FrozenNodeIterator):
271 raise InvalidArgumentException("Invalid type.")
272 if check_bbd and fni.best_before and datetime.fromtimestamp(fni.best_before) < datetime.now():
273 raise InvalidArgumentException("\"Best before\" date exceeded.")
274 iterator.thaw(fni)
275 is_resuming = True
276 start_index = iterator.total_index
277 context.log("Resuming from {}.".format(resume_file_path))
278 except (InvalidArgumentException, LZMAError, json.decoder.JSONDecodeError) as exc:
279 context.error("Warning: Not resuming from {}: {}".format(resume_file_path, exc))
280 try:
281 yield is_resuming, start_index
282 except (KeyboardInterrupt, AbortDownloadException):
283 if os.path.dirname(resume_file_path):
284 os.makedirs(os.path.dirname(resume_file_path), exist_ok=True)
285 save(iterator.freeze(), resume_file_path)
286 context.log("\nSaved resume information to {}.".format(resume_file_path))
287 raise
288 if resume_file_exists:
289 os.unlink(resume_file_path)
290 context.log("Iteration complete, deleted resume information file {}.".format(resume_file_path))
(New empty file)
0 from typing import Any, Callable, Dict, Iterator, Optional, TypeVar
1
2 from .instaloadercontext import InstaloaderContext
3
4 T = TypeVar('T')
5
6
7 class SectionIterator(Iterator[T]):
8 """Iterator for the new 'sections'-style responses.
9
10 .. versionadded:: 4.9"""
11 def __init__(self,
12 context: InstaloaderContext,
13 sections_extractor: Callable[[Dict[str, Any]], Dict[str, Any]],
14 media_wrapper: Callable[[Dict], T],
15 query_path: str,
16 first_data: Optional[Dict[str, Any]] = None):
17 self._context = context
18 self._sections_extractor = sections_extractor
19 self._media_wrapper = media_wrapper
20 self._query_path = query_path
21 self._data = first_data or self._query()
22 self._page_index = 0
23 self._section_index = 0
24
25 def __iter__(self):
26 return self
27
28 def _query(self, max_id: Optional[str] = None) -> Dict[str, Any]:
29 pagination_variables = {"max_id": max_id} if max_id is not None else {}
30 return self._sections_extractor(
31 self._context.get_json(self._query_path, params={"__a": 1, **pagination_variables})
32 )
33
34 def __next__(self) -> T:
35 if self._page_index < len(self._data['sections']):
36 media = self._data['sections'][self._page_index]['layout_content']['medias'][self._section_index]['media']
37 self._section_index += 1
38 if self._section_index >= len(self._data['sections'][self._page_index]['layout_content']['medias']):
39 self._section_index = 0
40 self._page_index += 1
41 return self._media_wrapper(media)
42 if self._data['more_available']:
43 self._page_index, self._section_index, self._data = 0, 0, self._query(self._data["next_max_id"])
44 return self.__next__()
45 raise StopIteration()
22 import re
33 from base64 import b64decode, b64encode
44 from collections import namedtuple
5 from contextlib import suppress
56 from datetime import datetime
6 from typing import Any, Dict, Iterator, List, Optional, Union
7 from itertools import islice
8 from pathlib import Path
9 from typing import Any, Dict, Iterable, Iterator, List, Optional, Tuple, Union
710
811 from . import __version__
912 from .exceptions import *
1013 from .instaloadercontext import InstaloaderContext
11
14 from .nodeiterator import FrozenNodeIterator, NodeIterator
15 from .sectioniterator import SectionIterator
1216
1317 PostSidecarNode = namedtuple('PostSidecarNode', ['is_video', 'display_url', 'video_url'])
1418 PostSidecarNode.__doc__ = "Item of a Sidecar Post."
2529
2630 PostComment = namedtuple('PostComment', (*PostCommentAnswer._fields, 'answers')) # type: ignore
2731 for field in PostCommentAnswer._fields:
28 getattr(PostComment, field).__doc__ = getattr(PostCommentAnswer, field).__doc__
32 getattr(PostComment, field).__doc__ = getattr(PostCommentAnswer, field).__doc__ # pylint: disable=no-member
2933 PostComment.answers.__doc__ = r"Iterator which yields all :class:`PostCommentAnswer`\ s for the comment." # type: ignore
3034
3135 PostLocation = namedtuple('PostLocation', ['id', 'name', 'slug', 'has_public_page', 'lat', 'lng'])
8690 def from_mediaid(cls, context: InstaloaderContext, mediaid: int):
8791 """Create a post object from a given mediaid"""
8892 return cls.from_shortcode(context, Post.mediaid_to_shortcode(mediaid))
93
94 @classmethod
95 def from_iphone_struct(cls, context: InstaloaderContext, media: Dict[str, Any]):
96 """Create a post from a given iphone_struct.
97
98 .. versionadded:: 4.9"""
99 media_types = {
100 1: "GraphImage",
101 2: "GraphVideo",
102 8: "GraphSidecar",
103 }
104 fake_node = {
105 "shortcode": media["code"],
106 "id": media["pk"],
107 "__typename": media_types[media["media_type"]],
108 "is_video": media_types[media["media_type"]] == "GraphVideo",
109 "date": media["taken_at"],
110 "caption": media["caption"].get("text") if media.get("caption") is not None else None,
111 "title": media.get("title"),
112 "viewer_has_liked": media["has_liked"],
113 "edge_media_preview_like": {"count": media["like_count"]},
114 "iphone_struct": media,
115 }
116 with suppress(KeyError):
117 fake_node["display_url"] = media['image_versions2']['candidates'][0]['url']
118 with suppress(KeyError):
119 fake_node["video_url"] = media['video_versions'][-1]['url']
120 fake_node["video_duration"] = media["video_duration"]
121 fake_node["video_view_count"] = media["view_count"]
122 with suppress(KeyError):
123 fake_node["edge_sidecar_to_children"] = {"edges": [{"node": {
124 "display_url": node['image_versions2']['candidates'][0]['url'],
125 "is_video": media_types[node["media_type"]] == "GraphVideo",
126 }} for node in media["carousel_media"]]}
127 return cls(context, fake_node, Profile.from_iphone_struct(context, media["user"]) if "user" in media else None)
89128
90129 @staticmethod
91130 def shortcode_to_mediaid(code: str) -> int:
127166 """The mediaid is a decimal representation of the media shortcode."""
128167 return int(self._node['id'])
129168
169 @property
170 def title(self) -> Optional[str]:
171 """Title of post"""
172 try:
173 return self._field('title')
174 except KeyError:
175 return None
176
130177 def __repr__(self):
131178 return '<Post {}>'.format(self.shortcode)
132179
146193 )
147194 self._full_metadata_dict = pic_json['data']['shortcode_media']
148195 if self._full_metadata_dict is None:
149 # issue #449
150 self._context.error("Fetching Post metadata failed (issue #449). "
151 "The following data has been returned:\n"
152 + json.dumps(pic_json['entry_data'], indent=2))
153196 raise BadResponseException("Fetching Post metadata failed.")
154197 if self.shortcode != self._full_metadata_dict['shortcode']:
155198 self._node.update(self._full_metadata_dict)
163206
164207 @property
165208 def _iphone_struct(self) -> Dict[str, Any]:
209 if not self._context.iphone_support:
210 raise IPhoneSupportDisabledException("iPhone support is disabled.")
166211 if not self._context.is_logged_in:
167212 raise LoginRequiredException("--login required to access iPhone media info endpoint.")
168213 if not self._iphone_struct_:
206251 @property
207252 def owner_id(self) -> int:
208253 """The ID of the Post's owner."""
209 return self.owner_profile.userid
254 # The ID may already be available, e.g. if the post instance was created
255 # from an `hashtag.get_posts()` iterator, so no need to make another
256 # http request.
257 if 'owner' in self._node and 'id' in self._node['owner']:
258 return self._node['owner']['id']
259 else:
260 return self.owner_profile.userid
210261
211262 @property
212263 def date_local(self) -> datetime:
235286 @property
236287 def url(self) -> str:
237288 """URL of the picture / video thumbnail of the post"""
238 if self.typename == "GraphImage" and self._context.is_logged_in:
289 if self.typename == "GraphImage" and self._context.iphone_support and self._context.is_logged_in:
239290 try:
240291 orig_url = self._iphone_struct['image_versions2']['candidates'][0]['url']
241 url = re.sub(r'&se=\d+(&?)', r'\1', orig_url)
292 url = re.sub(r'([?&])se=\d+&?', r'\1', orig_url).rstrip('&')
242293 return url
243294 except (InstaloaderException, KeyError, IndexError) as err:
244295 self._context.error('{} Unable to fetch high quality image version of {}.'.format(err, self))
249300 """Type of post, GraphImage, GraphVideo or GraphSidecar"""
250301 return self._field('__typename')
251302
252 def get_sidecar_nodes(self) -> Iterator[PostSidecarNode]:
253 """Sidecar nodes of a Post with typename==GraphSidecar."""
303 @property
304 def mediacount(self) -> int:
305 """
306 The number of media in a sidecar Post, or 1 if the Post it not a sidecar.
307
308 .. versionadded:: 4.6
309 """
254310 if self.typename == 'GraphSidecar':
255311 edges = self._field('edge_sidecar_to_children', 'edges')
256 if any(edge['node']['is_video'] for edge in edges):
312 return len(edges)
313 return 1
314
315 def get_is_videos(self) -> List[bool]:
316 """
317 Return a list containing the ``is_video`` property for each media in the post.
318
319 .. versionadded:: 4.7
320 """
321 if self.typename == 'GraphSidecar':
322 edges = self._field('edge_sidecar_to_children', 'edges')
323 return [edge['node']['is_video'] for edge in edges]
324 return [self.is_video]
325
326 def get_sidecar_nodes(self, start=0, end=-1) -> Iterator[PostSidecarNode]:
327 """
328 Sidecar nodes of a Post with typename==GraphSidecar.
329
330 .. versionchanged:: 4.6
331 Added parameters *start* and *end* to specify a slice of sidecar media.
332 """
333 if self.typename == 'GraphSidecar':
334 edges = self._field('edge_sidecar_to_children', 'edges')
335 if end < 0:
336 end = len(edges)-1
337 if start < 0:
338 start = len(edges)-1
339 if any(edge['node']['is_video'] and 'video_url' not in edge['node'] for edge in edges[start:(end+1)]):
257340 # video_url is only present in full metadata, issue #558.
258341 edges = self._full_metadata['edge_sidecar_to_children']['edges']
259342 for idx, edge in enumerate(edges):
260 node = edge['node']
261 is_video = node['is_video']
262 display_url = node['display_url']
263 if not is_video and self._context.is_logged_in:
264 try:
265 carousel_media = self._iphone_struct['carousel_media']
266 orig_url = carousel_media[idx]['image_versions2']['candidates'][0]['url']
267 display_url = re.sub(r'&se=\d+(&?)', r'\1', orig_url)
268 except (InstaloaderException, KeyError, IndexError) as err:
269 self._context.error('{} Unable to fetch high quality image version of {}.'.format(err, self))
270 yield PostSidecarNode(is_video=is_video, display_url=display_url,
271 video_url=node['video_url'] if is_video else None)
343 if start <= idx <= end:
344 node = edge['node']
345 is_video = node['is_video']
346 display_url = node['display_url']
347 if not is_video and self._context.iphone_support and self._context.is_logged_in:
348 try:
349 carousel_media = self._iphone_struct['carousel_media']
350 orig_url = carousel_media[idx]['image_versions2']['candidates'][0]['url']
351 display_url = re.sub(r'([?&])se=\d+&?', r'\1', orig_url).rstrip('&')
352 except (InstaloaderException, KeyError, IndexError) as err:
353 self._context.error('{} Unable to fetch high quality image version of {}.'.format(
354 err, self))
355 yield PostSidecarNode(is_video=is_video, display_url=display_url,
356 video_url=node['video_url'] if is_video else None)
272357
273358 @property
274359 def caption(self) -> Optional[str]:
294379 """List of all lowercased profiles that are mentioned in the Post's caption, without preceeding @."""
295380 if not self.caption:
296381 return []
297 # This regular expression is from jStassen, adjusted to use Python's \w to support Unicode
382 # This regular expression is modified from jStassen, adjusted to use Python's \w to
383 # support Unicode and a word/beginning of string delimiter at the beginning to ensure
384 # that no email addresses join the list of mentions.
298385 # http://blog.jstassen.com/2016/03/code-regex-for-instagram-username-and-hashtags/
299 mention_regex = re.compile(r"(?:@)(\w(?:(?:\w|(?:\.(?!\.))){0,28}(?:\w))?)")
386 mention_regex = re.compile(r"(?:^|\W|_)(?:@)(\w(?:(?:\w|(?:\.(?!\.))){0,28}(?:\w))?)")
300387 return re.findall(mention_regex, self.caption.lower())
301388
302389 @property
308395 pcaption = ' '.join([s.replace('/', '\u2215') for s in caption.splitlines() if s]).strip()
309396 return (pcaption[:30] + u"\u2026") if len(pcaption) > 31 else pcaption
310397 return _elliptify(self.caption) if self.caption else ''
398
399 @property
400 def accessibility_caption(self) -> Optional[str]:
401 """Accessibility caption of the post, if available.
402
403 .. versionadded:: 4.9"""
404 try:
405 return self._field("accessibility_caption")
406 except KeyError:
407 return None
311408
312409 @property
313410 def tagged_users(self) -> List[str]:
327424 def video_url(self) -> Optional[str]:
328425 """URL of the video, or None."""
329426 if self.is_video:
330 return self._field('video_url')
427 version_urls = []
428 try:
429 version_urls.append(self._field('video_url'))
430 except (InstaloaderException, KeyError, IndexError) as err:
431 self._context.error(f"Warning: Unable to fetch video from graphql of {self}: {err}")
432 if self._context.iphone_support and self._context.is_logged_in:
433 try:
434 version_urls.extend(version['url'] for version in self._iphone_struct['video_versions'])
435 except (InstaloaderException, KeyError, IndexError) as err:
436 self._context.error(f"Unable to fetch high-quality video version of {self}: {err}")
437 version_urls = list(dict.fromkeys(version_urls))
438 if len(version_urls) == 0:
439 return None
440 if len(version_urls) == 1:
441 return version_urls[0]
442 url_candidates: List[Tuple[int, str]] = []
443 for idx, version_url in enumerate(version_urls):
444 try:
445 url_candidates.append((
446 int(self._context.head(version_url, allow_redirects=True).headers.get('Content-Length', 0)),
447 version_url
448 ))
449 except (InstaloaderException, KeyError, IndexError) as err:
450 self._context.error(f"Video URL candidate {idx+1}/{len(version_urls)} for {self}: {err}")
451 if not url_candidates:
452 # All candidates fail: Fallback to default URL and handle errors later at the actual download attempt
453 return version_urls[0]
454 url_candidates.sort()
455 return url_candidates[-1][1]
331456 return None
332457
333458 @property
375500 except KeyError:
376501 return self._field('edge_media_to_comment', 'count')
377502
378 def get_comments(self) -> Iterator[PostComment]:
503 def get_comments(self) -> Iterable[PostComment]:
379504 r"""Iterate over all comments of the post.
380505
381506 Each comment is represented by a PostComment namedtuple with fields text (string), created_at (datetime),
382507 id (int), owner (:class:`Profile`) and answers (:class:`~typing.Iterator`\ [:class:`PostCommentAnswer`])
383508 if available.
509
510 .. versionchanged:: 4.7
511 Change return type to ``Iterable``.
384512 """
385513 def _postcommentanswer(node):
386514 return PostCommentAnswer(id=int(node['id']),
401529 # If the answer's metadata already contains all comments, don't do GraphQL requests to obtain them
402530 yield from (_postcommentanswer(comment['node']) for comment in answer_edges)
403531 return
404 yield from (_postcommentanswer(answer_node) for answer_node in
405 self._context.graphql_node_list("51fdd02b67508306ad4484ff574a0b62",
406 {'comment_id': node['id']},
407 'https://www.instagram.com/p/' + self.shortcode + '/',
408 lambda d: d['data']['comment']['edge_threaded_comments']))
532 yield from NodeIterator(
533 self._context,
534 '51fdd02b67508306ad4484ff574a0b62',
535 lambda d: d['data']['comment']['edge_threaded_comments'],
536 _postcommentanswer,
537 {'comment_id': node['id']},
538 'https://www.instagram.com/p/{0}/'.format(self.shortcode),
539 )
409540
410541 def _postcomment(node):
411542 return PostComment(*_postcommentanswer(node),
412543 answers=_postcommentanswers(node))
413544 if self.comments == 0:
414545 # Avoid doing additional requests if there are no comments
415 return
546 return []
416547
417548 comment_edges = self._field('edge_media_to_comment', 'edges')
418549 answers_count = sum([edge['node'].get('edge_threaded_comments', {}).get('count', 0) for edge in comment_edges])
419550
420551 if self.comments == len(comment_edges) + answers_count:
421552 # If the Post's metadata already contains all parent comments, don't do GraphQL requests to obtain them
422 yield from (_postcomment(comment['node']) for comment in comment_edges)
423 return
424 yield from (_postcomment(node) for node in
425 self._context.graphql_node_list(
426 "97b41c52301f77ce508f55e66d17620e",
427 {'shortcode': self.shortcode},
428 'https://www.instagram.com/p/' + self.shortcode + '/',
429 lambda d: d['data']['shortcode_media']['edge_media_to_parent_comment']))
553 return [_postcomment(comment['node']) for comment in comment_edges]
554 return NodeIterator(
555 self._context,
556 '97b41c52301f77ce508f55e66d17620e',
557 lambda d: d['data']['shortcode_media']['edge_media_to_parent_comment'],
558 _postcomment,
559 {'shortcode': self.shortcode},
560 'https://www.instagram.com/p/{0}/'.format(self.shortcode),
561 )
430562
431563 def get_likes(self) -> Iterator['Profile']:
432 """Iterate over all likes of the post. A :class:`Profile` instance of each likee is yielded."""
564 """
565 Iterate over all likes of the post. A :class:`Profile` instance of each likee is yielded.
566
567 .. versionchanged:: 4.5.4
568 Require being logged in (as required by Instagram).
569 """
570 if not self._context.is_logged_in:
571 raise LoginRequiredException("--login required to access likes of a post.")
433572 if self.likes == 0:
434573 # Avoid doing additional requests if there are no comments
435574 return
438577 # If the Post's metadata already contains all likes, don't do GraphQL requests to obtain them
439578 yield from (Profile(self._context, like['node']) for like in likes_edges)
440579 return
441 yield from (Profile(self._context, node) for node in
442 self._context.graphql_node_list("1cb6ec562846122743b61e492c85999f", {'shortcode': self.shortcode},
443 'https://www.instagram.com/p/' + self.shortcode + '/',
444 lambda d: d['data']['shortcode_media']['edge_liked_by']))
580 yield from NodeIterator(
581 self._context,
582 '1cb6ec562846122743b61e492c85999f',
583 lambda d: d['data']['shortcode_media']['edge_liked_by'],
584 lambda n: Profile(self._context, n),
585 {'shortcode': self.shortcode},
586 'https://www.instagram.com/p/{0}/'.format(self.shortcode),
587 )
445588
446589 @property
447590 def is_sponsored(self) -> bool:
482625 return None
483626 location_id = int(loc['id'])
484627 if any(k not in loc for k in ('name', 'slug', 'has_public_page', 'lat', 'lng')):
485 loc = self._context.get_json("explore/locations/{0}/".format(location_id),
486 params={'__a': 1})['graphql']['location']
628 loc.update(self._context.get_json("explore/locations/{0}/".format(location_id),
629 params={'__a': 1})['native_location_data']['location_info'])
487630 self._location = PostLocation(location_id, loc['name'], loc['slug'], loc['has_public_page'],
488631 loc['lat'], loc['lng'])
489632 return self._location
539682 """
540683 # pylint:disable=protected-access
541684 profile = cls(context, {'username': username.lower()})
542 profile._obtain_metadata() # to raise ProfileNotExistException now in case username is invalid
685 profile._obtain_metadata() # to raise ProfileNotExistsException now in case username is invalid
543686 return profile
544687
545688 @classmethod
569712 context.profile_id_cache[profile_id] = profile
570713 return profile
571714
715 @classmethod
716 def from_iphone_struct(cls, context: InstaloaderContext, media: Dict[str, Any]):
717 """Create a profile from a given iphone_struct.
718
719 .. versionadded:: 4.9"""
720 return cls(context, {
721 "id": media["pk"],
722 "username": media["username"],
723 "is_private": media["is_private"],
724 "full_name": media["full_name"],
725 "profile_pic_url_hd": media["profile_pic_url"],
726 "iphone_struct": media,
727 })
728
729 @classmethod
730 def own_profile(cls, context: InstaloaderContext):
731 """Return own profile if logged-in.
732
733 :param context: :attr:`Instaloader.context`
734
735 .. versionadded:: 4.5.2"""
736 if not context.is_logged_in:
737 raise LoginRequiredException("--login required to access own profile.")
738 return cls(context, context.graphql_query("d6f4427fbe92d846298cf93df0b937d3", {})["data"]["user"])
739
572740 def _asdict(self):
573741 json_node = self._node.copy()
574742 # remove posts to avoid "Circular reference detected" exception
611779
612780 @property
613781 def _iphone_struct(self) -> Dict[str, Any]:
782 if not self._context.iphone_support:
783 raise IPhoneSupportDisabledException("iPhone support is disabled.")
614784 if not self._context.is_logged_in:
615785 raise LoginRequiredException("--login required to access iPhone profile info endpoint.")
616786 if not self._iphone_struct_:
711881 def has_public_story(self) -> bool:
712882 if not self._has_public_story:
713883 self._obtain_metadata()
714 # query not rate limited if invoked anonymously:
715 with self._context.anonymous_copy() as anonymous_context:
716 data = anonymous_context.graphql_query('9ca88e465c3f866a76f7adee3871bdd8',
717 {'user_id': self.userid, 'include_chaining': False,
718 'include_reel': False, 'include_suggested_users': False,
719 'include_logged_out_extras': True,
720 'include_highlight_reels': False},
721 'https://www.instagram.com/{}/'.format(self.username))
884 # query rate might be limited:
885 data = self._context.graphql_query('9ca88e465c3f866a76f7adee3871bdd8',
886 {'user_id': self.userid, 'include_chaining': False,
887 'include_reel': False, 'include_suggested_users': False,
888 'include_logged_out_extras': True,
889 'include_highlight_reels': False},
890 'https://www.instagram.com/{}/'.format(self.username))
722891 self._has_public_story = data['data']['user']['has_public_story']
723892 assert self._has_public_story is not None
724893 return self._has_public_story
754923
755924 .. versionchanged:: 4.2.1
756925 Require being logged in for HD version (as required by Instagram)."""
757 if self._context.is_logged_in:
926 if self._context.iphone_support and self._context.is_logged_in:
758927 try:
759928 return self._iphone_struct['hd_profile_pic_url_info']['url']
760929 except (InstaloaderException, KeyError) as err:
769938 Use :attr:`profile_pic_url`."""
770939 return self.profile_pic_url
771940
772 def get_posts(self) -> Iterator[Post]:
773 """Retrieve all posts from a profile."""
941 def get_posts(self) -> NodeIterator[Post]:
942 """Retrieve all posts from a profile.
943
944 :rtype: NodeIterator[Post]"""
774945 self._obtain_metadata()
775 yield from (Post(self._context, node, self) for node in
776 self._context.graphql_node_list("472f257a40c653c64c666ce877d59d2b",
777 {'id': self.userid},
778 'https://www.instagram.com/{0}/'.format(self.username),
779 lambda d: d['data']['user']['edge_owner_to_timeline_media'],
780 first_data=self._metadata('edge_owner_to_timeline_media')))
781
782 def get_saved_posts(self) -> Iterator[Post]:
783 """Get Posts that are marked as saved by the user."""
946 return NodeIterator(
947 self._context,
948 '003056d32c2554def87228bc3fd9668a',
949 lambda d: d['data']['user']['edge_owner_to_timeline_media'],
950 lambda n: Post(self._context, n, self),
951 {'id': self.userid},
952 'https://www.instagram.com/{0}/'.format(self.username),
953 self._metadata('edge_owner_to_timeline_media'),
954 )
955
956 def get_saved_posts(self) -> NodeIterator[Post]:
957 """Get Posts that are marked as saved by the user.
958
959 :rtype: NodeIterator[Post]"""
784960
785961 if self.username != self._context.username:
786962 raise LoginRequiredException("--login={} required to get that profile's saved posts.".format(self.username))
787963
788 self._obtain_metadata()
789 yield from (Post(self._context, node) for node in
790 self._context.graphql_node_list("f883d95537fbcd400f466f63d42bd8a1",
791 {'id': self.userid},
792 'https://www.instagram.com/{0}/'.format(self.username),
793 lambda d: d['data']['user']['edge_saved_media'],
794 first_data=self._metadata('edge_saved_media')))
795
796 def get_tagged_posts(self) -> Iterator[Post]:
964 return NodeIterator(
965 self._context,
966 'f883d95537fbcd400f466f63d42bd8a1',
967 lambda d: d['data']['user']['edge_saved_media'],
968 lambda n: Post(self._context, n),
969 {'id': self.userid},
970 'https://www.instagram.com/{0}/'.format(self.username),
971 )
972
973 def get_tagged_posts(self) -> NodeIterator[Post]:
797974 """Retrieve all posts where a profile is tagged.
975
976 :rtype: NodeIterator[Post]
798977
799978 .. versionadded:: 4.0.7"""
800979 self._obtain_metadata()
801 yield from (Post(self._context, node, self if int(node['owner']['id']) == self.userid else None) for node in
802 self._context.graphql_node_list("e31a871f7301132ceaab56507a66bbb7",
803 {'id': self.userid},
804 'https://www.instagram.com/{0}/'.format(self.username),
805 lambda d: d['data']['user']['edge_user_to_photos_of_you']))
806
807 def get_igtv_posts(self) -> Iterator[Post]:
980 return NodeIterator(
981 self._context,
982 'e31a871f7301132ceaab56507a66bbb7',
983 lambda d: d['data']['user']['edge_user_to_photos_of_you'],
984 lambda n: Post(self._context, n, self if int(n['owner']['id']) == self.userid else None),
985 {'id': self.userid},
986 'https://www.instagram.com/{0}/'.format(self.username),
987 )
988
989 def get_igtv_posts(self) -> NodeIterator[Post]:
808990 """Retrieve all IGTV posts.
991
992 :rtype: NodeIterator[Post]
809993
810994 .. versionadded:: 4.3"""
811995 self._obtain_metadata()
812 yield from (Post(self._context, node, self) for node in
813 self._context.graphql_node_list('bc78b344a68ed16dd5d7f264681c4c76',
814 {'id': self.userid},
815 'https://www.instagram.com/{0}/channel/'.format(self.username),
816 lambda d: d['data']['user']['edge_felix_video_timeline'],
817 first_data=self._metadata('edge_felix_video_timeline')))
818
819 def get_followers(self) -> Iterator['Profile']:
996 return NodeIterator(
997 self._context,
998 'bc78b344a68ed16dd5d7f264681c4c76',
999 lambda d: d['data']['user']['edge_felix_video_timeline'],
1000 lambda n: Post(self._context, n, self),
1001 {'id': self.userid},
1002 'https://www.instagram.com/{0}/channel/'.format(self.username),
1003 self._metadata('edge_felix_video_timeline'),
1004 )
1005
1006 def get_followers(self) -> NodeIterator['Profile']:
8201007 """
8211008 Retrieve list of followers of given profile.
8221009 To use this, one needs to be logged in and private profiles has to be followed.
1010
1011 :rtype: NodeIterator[Profile]
8231012 """
8241013 if not self._context.is_logged_in:
8251014 raise LoginRequiredException("--login required to get a profile's followers.")
8261015 self._obtain_metadata()
827 yield from (Profile(self._context, node) for node in
828 self._context.graphql_node_list("37479f2b8209594dde7facb0d904896a",
829 {'id': str(self.userid)},
830 'https://www.instagram.com/' + self.username + '/',
831 lambda d: d['data']['user']['edge_followed_by']))
832
833 def get_followees(self) -> Iterator['Profile']:
1016 return NodeIterator(
1017 self._context,
1018 '37479f2b8209594dde7facb0d904896a',
1019 lambda d: d['data']['user']['edge_followed_by'],
1020 lambda n: Profile(self._context, n),
1021 {'id': str(self.userid)},
1022 'https://www.instagram.com/{0}/'.format(self.username),
1023 )
1024
1025 def get_followees(self) -> NodeIterator['Profile']:
8341026 """
8351027 Retrieve list of followees (followings) of given profile.
8361028 To use this, one needs to be logged in and private profiles has to be followed.
1029
1030 :rtype: NodeIterator[Profile]
8371031 """
8381032 if not self._context.is_logged_in:
8391033 raise LoginRequiredException("--login required to get a profile's followees.")
8401034 self._obtain_metadata()
841 yield from (Profile(self._context, node) for node in
842 self._context.graphql_node_list("58712303d941c6855d4e888c5f0cd22f",
843 {'id': str(self.userid)},
844 'https://www.instagram.com/' + self.username + '/',
845 lambda d: d['data']['user']['edge_follow']))
1035 return NodeIterator(
1036 self._context,
1037 '58712303d941c6855d4e888c5f0cd22f',
1038 lambda d: d['data']['user']['edge_follow'],
1039 lambda n: Profile(self._context, n),
1040 {'id': str(self.userid)},
1041 'https://www.instagram.com/{0}/'.format(self.username),
1042 )
8461043
8471044 def get_similar_accounts(self) -> Iterator['Profile']:
8481045 """
8761073 self._context = context
8771074 self._node = node
8781075 self._owner_profile = owner_profile
1076 self._iphone_struct_ = None
1077 if 'iphone_struct' in node:
1078 # if loaded from JSON with load_structure_from_file()
1079 self._iphone_struct_ = node['iphone_struct']
8791080
8801081 def _asdict(self):
8811082 node = self._node
8821083 if self._owner_profile:
8831084 node['owner'] = self._owner_profile._asdict()
1085 if self._iphone_struct_:
1086 node['iphone_struct'] = self._iphone_struct_
8841087 return node
8851088
8861089 @property
9041107
9051108 def __hash__(self) -> int:
9061109 return hash(self.mediaid)
1110
1111 @property
1112 def _iphone_struct(self) -> Dict[str, Any]:
1113 if not self._context.iphone_support:
1114 raise IPhoneSupportDisabledException("iPhone support is disabled.")
1115 if not self._context.is_logged_in:
1116 raise LoginRequiredException("--login required to access iPhone media info endpoint.")
1117 if not self._iphone_struct_:
1118 data = self._context.get_iphone_json(path='api/v1/media/{}/info/'.format(self.mediaid), params={})
1119 self._iphone_struct_ = data['items'][0]
1120 return self._iphone_struct_
9071121
9081122 @property
9091123 def owner_profile(self) -> Profile:
9561170 @property
9571171 def url(self) -> str:
9581172 """URL of the picture / video thumbnail of the StoryItem"""
1173 if self.typename == "GraphStoryImage" and self._context.iphone_support and self._context.is_logged_in:
1174 try:
1175 orig_url = self._iphone_struct['image_versions2']['candidates'][0]['url']
1176 url = re.sub(r'([?&])se=\d+&?', r'\1', orig_url).rstrip('&')
1177 return url
1178 except (InstaloaderException, KeyError, IndexError) as err:
1179 self._context.error('{} Unable to fetch high quality image version of {}.'.format(err, self))
9591180 return self._node['display_resources'][-1]['src']
9601181
9611182 @property
9721193 def video_url(self) -> Optional[str]:
9731194 """URL of the video, or None."""
9741195 if self.is_video:
975 return self._node['video_resources'][-1]['src']
1196 version_urls = []
1197 try:
1198 version_urls.append(self._node['video_resources'][-1]['src'])
1199 except (InstaloaderException, KeyError, IndexError) as err:
1200 self._context.error(f"Warning: Unable to fetch video from graphql of {self}: {err}")
1201 if self._context.iphone_support and self._context.is_logged_in:
1202 try:
1203 version_urls.extend(version['url'] for version in self._iphone_struct['video_versions'])
1204 except (InstaloaderException, KeyError, IndexError) as err:
1205 self._context.error(f"Unable to fetch high-quality video version of {self}: {err}")
1206 version_urls = list(dict.fromkeys(version_urls))
1207 if len(version_urls) == 0:
1208 return None
1209 if len(version_urls) == 1:
1210 return version_urls[0]
1211 url_candidates: List[Tuple[int, str]] = []
1212 for idx, version_url in enumerate(version_urls):
1213 try:
1214 url_candidates.append((
1215 int(self._context.head(version_url, allow_redirects=True).headers.get('Content-Length', 0)),
1216 version_url
1217 ))
1218 except (InstaloaderException, KeyError, IndexError) as err:
1219 self._context.error(f"Video URL candidate {idx+1}/{len(version_urls)} for {self}: {err}")
1220 if not url_candidates:
1221 # All candidates fail: Fallback to default URL and handle errors later at the actual download attempt
1222 return version_urls[0]
1223 url_candidates.sort()
1224 return url_candidates[-1][1]
9761225 return None
9771226
9781227
10281277
10291278 @property
10301279 def last_seen_local(self) -> Optional[datetime]:
1031 """Timestamp when the story has last been watched or None (local time zone)."""
1280 """Timestamp of the most recent StoryItem that has been watched or None (local time zone)."""
10321281 if self._node['seen']:
10331282 return datetime.fromtimestamp(self._node['seen'])
10341283 return None
10351284
10361285 @property
10371286 def last_seen_utc(self) -> Optional[datetime]:
1038 """Timestamp when the story has last been watched or None (UTC)."""
1287 """Timestamp of the most recent StoryItem that has been watched or None (UTC)."""
10391288 if self._node['seen']:
10401289 return datetime.utcfromtimestamp(self._node['seen'])
10411290 return None
11711420 L.download_post(post, target="#"+hashtag.name)
11721421
11731422 Also, this class implements == and is hashable.
1423
1424 .. versionchanged:: 4.9
1425 Removed ``get_related_tags()`` and ``is_top_media_only`` as these features were removed from Instagram.
11741426 """
11751427 def __init__(self, context: InstaloaderContext, node: Dict[str, Any]):
11761428 assert "name" in node
11991451 return self._node["name"].lower()
12001452
12011453 def _query(self, params):
1202 return self._context.get_json("explore/tags/{0}/".format(self.name),
1203 params)["graphql"]["hashtag"]
1454 json_response = self._context.get_json("explore/tags/{0}/".format(self.name), params)
1455 return json_response["graphql"]["hashtag"] if "graphql" in json_response else json_response["data"]
12041456
12051457 def _obtain_metadata(self):
12061458 if not self._has_full_metadata:
12111463 json_node = self._node.copy()
12121464 # remove posts
12131465 json_node.pop("edge_hashtag_to_top_posts", None)
1466 json_node.pop("top", None)
12141467 json_node.pop("edge_hashtag_to_media", None)
1468 json_node.pop("recent", None)
12151469 return json_node
12161470
12171471 def __repr__(self):
12471501 return self._metadata("profile_pic_url")
12481502
12491503 @property
1250 def description(self) -> str:
1504 def description(self) -> Optional[str]:
12511505 return self._metadata("description")
12521506
12531507 @property
12541508 def allow_following(self) -> bool:
1255 return self._metadata("allow_following")
1509 return bool(self._metadata("allow_following"))
12561510
12571511 @property
12581512 def is_following(self) -> bool:
1259 return self._metadata("is_following")
1260
1261 @property
1262 def is_top_media_only(self) -> bool:
1263 return self._metadata("is_top_media_only")
1264
1265 def get_related_tags(self) -> Iterator["Hashtag"]:
1266 """Yields similar hashtags."""
1267 yield from (Hashtag(self._context, edge["node"])
1268 for edge in self._metadata("edge_hashtag_to_related_tags", "edges"))
1513 try:
1514 return self._metadata("is_following")
1515 except KeyError:
1516 return bool(self._metadata("following"))
12691517
12701518 def get_top_posts(self) -> Iterator[Post]:
12711519 """Yields the top posts of the hashtag."""
1272 yield from (Post(self._context, edge["node"])
1273 for edge in self._metadata("edge_hashtag_to_top_posts", "edges"))
1520 try:
1521 yield from (Post(self._context, edge["node"])
1522 for edge in self._metadata("edge_hashtag_to_top_posts", "edges"))
1523 except KeyError:
1524 yield from SectionIterator(
1525 self._context,
1526 lambda d: d["data"]["top"],
1527 lambda m: Post.from_iphone_struct(self._context, m),
1528 f"explore/tags/{self.name}/",
1529 self._metadata("top"),
1530 )
12741531
12751532 @property
12761533 def mediacount(self) -> int:
12801537 The number of posts with a certain hashtag may differ from the number of posts that can actually be accessed, as
12811538 the hashtag count might include private posts
12821539 """
1283 return self._metadata("edge_hashtag_to_media", "count")
1540 try:
1541 return self._metadata("edge_hashtag_to_media", "count")
1542 except KeyError:
1543 return self._metadata("media_count")
12841544
12851545 def get_posts(self) -> Iterator[Post]:
1286 """Yields the posts associated with this hashtag."""
1287 self._metadata("edge_hashtag_to_media", "edges")
1288 self._metadata("edge_hashtag_to_media", "page_info")
1289 conn = self._metadata("edge_hashtag_to_media")
1290 yield from (Post(self._context, edge["node"]) for edge in conn["edges"])
1291 while conn["page_info"]["has_next_page"]:
1292 data = self._query({'__a': 1, 'max_id': conn["page_info"]["end_cursor"]})
1293 conn = data["edge_hashtag_to_media"]
1546 """Yields the recent posts associated with this hashtag."""
1547 try:
1548 self._metadata("edge_hashtag_to_media", "edges")
1549 self._metadata("edge_hashtag_to_media", "page_info")
1550 conn = self._metadata("edge_hashtag_to_media")
12941551 yield from (Post(self._context, edge["node"]) for edge in conn["edges"])
1552 while conn["page_info"]["has_next_page"]:
1553 data = self._query({'__a': 1, 'max_id': conn["page_info"]["end_cursor"]})
1554 conn = data["edge_hashtag_to_media"]
1555 yield from (Post(self._context, edge["node"]) for edge in conn["edges"])
1556 except KeyError:
1557 yield from SectionIterator(
1558 self._context,
1559 lambda d: d["data"]["recent"],
1560 lambda m: Post.from_iphone_struct(self._context, m),
1561 f"explore/tags/{self.name}/",
1562 self._metadata("recent"),
1563 )
12951564
12961565 def get_all_posts(self) -> Iterator[Post]:
1297 """Yields all posts, i.e. all most recent posts and the top posts, in chronological order."""
1298 sorted_top_posts = iter(sorted(self.get_top_posts(), key=lambda p: p.date_utc, reverse=True))
1566 """Yields all posts, i.e. all most recent posts and the top posts, in almost-chronological order."""
1567 sorted_top_posts = iter(sorted(islice(self.get_top_posts(), 9), key=lambda p: p.date_utc, reverse=True))
12991568 other_posts = self.get_posts()
13001569 next_top = next(sorted_top_posts, None)
13011570 next_other = next(other_posts, None)
13021571 while next_top is not None or next_other is not None:
13031572 if next_other is None:
1573 assert next_top is not None
1574 yield next_top
13041575 yield from sorted_top_posts
13051576 break
13061577 if next_top is None:
1578 assert next_other is not None
1579 yield next_other
13071580 yield from other_posts
13081581 break
13091582 if next_top == next_other:
13181591 yield next_other
13191592 next_other = next(other_posts, None)
13201593
1594 def get_posts_resumable(self) -> NodeIterator[Post]:
1595 """Get the recent posts of the hashtag in a resumable fashion.
1596
1597 :rtype: NodeIterator[Post]
1598
1599 .. versionadded:: 4.9"""
1600 return NodeIterator(
1601 self._context, "9b498c08113f1e09617a1703c22b2f32",
1602 lambda d: d['data']['hashtag']['edge_hashtag_to_media'],
1603 lambda n: Post(self._context, n),
1604 {'tag_name': self.name},
1605 f"https://www.instagram.com/explore/tags/{self.name}/"
1606 )
1607
13211608
13221609 class TopSearchResults:
13231610 """
13971684 return self._searchstring
13981685
13991686
1400 JsonExportable = Union[Post, Profile, StoryItem, Hashtag]
1687 class TitlePic:
1688 def __init__(self, profile: Optional[Profile], target: Union[str, Path], typename: str,
1689 filename: str, date_utc: Optional[datetime]):
1690 self._profile = profile
1691 self._target = target
1692 self._typename = typename
1693 self._filename = filename
1694 self._date_utc = date_utc
1695
1696 @property
1697 def profile(self) -> Union[str, Path]:
1698 return self._profile.username.lower() if self._profile is not None else self._target
1699
1700 @property
1701 def owner_username(self) -> Union[str, Path]:
1702 return self.profile
1703
1704 @property
1705 def owner_id(self) -> Union[str, Path]:
1706 return str(self._profile.userid) if self._profile is not None else self._target
1707
1708 @property
1709 def target(self) -> Union[str, Path]:
1710 return self._target
1711
1712 @property
1713 def typename(self) -> str:
1714 return self._typename
1715
1716 @property
1717 def filename(self) -> str:
1718 return self._filename
1719
1720 @property
1721 def date_utc(self) -> Optional[datetime]:
1722 return self._date_utc
1723
1724 @property
1725 def date(self) -> Optional[datetime]:
1726 return self.date_utc
1727
1728 @property
1729 def date_local(self) -> Optional[datetime]:
1730 return self._date_utc.astimezone() if self._date_utc is not None else None
1731
1732
1733 JsonExportable = Union[Post, Profile, StoryItem, Hashtag, FrozenNodeIterator]
1734
1735
1736 def get_json_structure(structure: JsonExportable) -> dict:
1737 """Returns Instaloader JSON structure for a :class:`Post`, :class:`Profile`, :class:`StoryItem`, :class:`Hashtag`
1738 or :class:`FrozenNodeIterator` so that it can be loaded by :func:`load_structure`.
1739
1740 :param structure: :class:`Post`, :class:`Profile`, :class:`StoryItem` or :class:`Hashtag`
1741
1742 .. versionadded:: 4.8
1743 """
1744 return {
1745 'node': structure._asdict(),
1746 'instaloader': {'version': __version__, 'node_type': structure.__class__.__name__}
1747 }
14011748
14021749
14031750 def save_structure_to_file(structure: JsonExportable, filename: str) -> None:
1404 """Saves a :class:`Post`, :class:`Profile`, :class:`StoryItem` or :class:`Hashtag` to a '.json' or '.json.xz' file
1405 such that it can later be loaded by :func:`load_structure_from_file`.
1751 """Saves a :class:`Post`, :class:`Profile`, :class:`StoryItem`, :class:`Hashtag` or :class:`FrozenNodeIterator` to a
1752 '.json' or '.json.xz' file such that it can later be loaded by :func:`load_structure_from_file`.
14061753
14071754 If the specified filename ends in '.xz', the file will be LZMA compressed. Otherwise, a pretty-printed JSON file
14081755 will be created.
14101757 :param structure: :class:`Post`, :class:`Profile`, :class:`StoryItem` or :class:`Hashtag`
14111758 :param filename: Filename, ends in '.json' or '.json.xz'
14121759 """
1413 json_structure = {'node': structure._asdict(),
1414 'instaloader': {'version': __version__, 'node_type': structure.__class__.__name__}}
1760 json_structure = get_json_structure(structure)
14151761 compress = filename.endswith('.xz')
14161762 if compress:
14171763 with lzma.open(filename, 'wt', check=lzma.CHECK_NONE) as fp:
14211767 json.dump(json_structure, fp=fp, indent=4, sort_keys=True)
14221768
14231769
1424 def load_structure_from_file(context: InstaloaderContext, filename: str) -> JsonExportable:
1425 """Loads a :class:`Post`, :class:`Profile`, :class:`StoryItem` or :class:`Hashtag` from a '.json' or '.json.xz' file
1426 that has been saved by :func:`save_structure_to_file`.
1770 def load_structure(context: InstaloaderContext, json_structure: dict) -> JsonExportable:
1771 """Loads a :class:`Post`, :class:`Profile`, :class:`StoryItem`, :class:`Hashtag` or :class:`FrozenNodeIterator` from
1772 a json structure.
14271773
14281774 :param context: :attr:`Instaloader.context` linked to the new object, used for additional queries if neccessary.
1429 :param filename: Filename, ends in '.json' or '.json.xz'
1775 :param json_structure: Instaloader JSON structure
1776
1777 .. versionadded:: 4.8
14301778 """
1431 compressed = filename.endswith('.xz')
1432 if compressed:
1433 fp = lzma.open(filename, 'rt')
1434 else:
1435 fp = open(filename, 'rt')
1436 json_structure = json.load(fp)
1437 fp.close()
14381779 if 'node' in json_structure and 'instaloader' in json_structure and \
14391780 'node_type' in json_structure['instaloader']:
14401781 node_type = json_structure['instaloader']['node_type']
14461787 return StoryItem(context, json_structure['node'])
14471788 elif node_type == "Hashtag":
14481789 return Hashtag(context, json_structure['node'])
1449 else:
1450 raise InvalidArgumentException("{}: Not an Instaloader JSON.".format(filename))
1790 elif node_type == "FrozenNodeIterator":
1791 if not 'first_node' in json_structure['node']:
1792 json_structure['node']['first_node'] = None
1793 return FrozenNodeIterator(**json_structure['node'])
14511794 elif 'shortcode' in json_structure:
14521795 # Post JSON created with Instaloader v3
14531796 return Post.from_shortcode(context, json_structure['shortcode'])
1797 raise InvalidArgumentException("Passed json structure is not an Instaloader JSON")
1798
1799
1800 def load_structure_from_file(context: InstaloaderContext, filename: str) -> JsonExportable:
1801 """Loads a :class:`Post`, :class:`Profile`, :class:`StoryItem`, :class:`Hashtag` or :class:`FrozenNodeIterator` from
1802 a '.json' or '.json.xz' file that has been saved by :func:`save_structure_to_file`.
1803
1804 :param context: :attr:`Instaloader.context` linked to the new object, used for additional queries if neccessary.
1805 :param filename: Filename, ends in '.json' or '.json.xz'
1806 """
1807 compressed = filename.endswith('.xz')
1808 if compressed:
1809 fp = lzma.open(filename, 'rt')
14541810 else:
1455 raise InvalidArgumentException("{}: Not an Instaloader JSON.".format(filename))
1811 # pylint:disable=consider-using-with
1812 fp = open(filename, 'rt')
1813 json_structure = json.load(fp)
1814 fp.close()
1815 return load_structure(context, json_structure)
22 import re
33 import sys
44 import os
5 import platform
65 from setuptools import setup
76
87
1817 raise SystemExit("Could not find version string.")
1918
2019
21 if sys.version_info < (3, 5):
22 sys.exit('Instaloader requires Python >= 3.5.')
20 if sys.version_info < (3, 6):
21 sys.exit('Instaloader requires Python >= 3.6.')
2322
2423 requirements = ['requests>=2.4']
25
26 if platform.system() == 'Windows' and sys.version_info < (3, 6):
27 requirements.append('win_unicode_console')
2824
2925 keywords = (['instagram', 'instagram-scraper', 'instagram-client', 'instagram-feed', 'downloader', 'videos', 'photos',
3026 'pictures', 'instagram-user-photos', 'instagram-photos', 'instagram-metadata', 'instagram-downloader',
3733 name='instaloader',
3834 version=get_version(),
3935 packages=['instaloader'],
36 package_data={'instaloader': ['py.typed']},
4037 url='https://instaloader.github.io/',
4138 license='MIT',
4239 author='Alexander Graf, André Koch-Kramer',
4542 'from Instagram.',
4643 long_description=open(os.path.join(SRC, 'README.rst')).read(),
4744 install_requires=requirements,
48 python_requires='>=3.5',
45 python_requires='>=3.6',
4946 entry_points={'console_scripts': ['instaloader=instaloader.__main__:main']},
50 zip_safe=True,
47 zip_safe=False,
5148 keywords=keywords,
5249 classifiers=[
5350 'Development Status :: 5 - Production/Stable',
5653 'Intended Audience :: Developers',
5754 'License :: OSI Approved :: MIT License',
5855 'Operating System :: OS Independent',
59 'Programming Language :: Python :: 3.5',
6056 'Programming Language :: Python :: 3.6',
6157 'Programming Language :: Python :: 3.7',
6258 'Programming Language :: Python :: 3.8',
59 'Programming Language :: Python :: 3.9',
6360 'Programming Language :: Python :: 3 :: Only',
6461 'Topic :: Internet',
6562 'Topic :: Multimedia :: Graphics'
44 import tempfile
55 import unittest
66 from itertools import islice
7 from typing import Dict, List
7 from typing import Optional
88
99 import instaloader
1010
2222 EMPTY_PROFILE = "not_public"
2323 EMPTY_PROFILE_ID = 1928659031
2424
25 # Preserve query timestamps (rate control) between tests to not get rate limited
26 instaloadercontext_query_timestamps = dict() # type: Dict[str, List[float]]
25 ratecontroller = None # type: Optional[instaloader.RateController]
2726
2827
2928 class TestInstaloaderAnonymously(unittest.TestCase):
3635 download_comments=True,
3736 save_metadata=True)
3837 self.L.context.raise_all_errors = True
39 # pylint:disable=protected-access
40 self.L.context._graphql_query_timestamps = instaloadercontext_query_timestamps.copy()
38 if ratecontroller is not None:
39 # pylint:disable=protected-access
40 ratecontroller._context = self.L.context
41 self.L.context._rate_controller = ratecontroller
4142
4243 def tearDown(self):
4344 # pylint:disable=global-statement,protected-access
44 global instaloadercontext_query_timestamps
45 instaloadercontext_query_timestamps = self.L.context._graphql_query_timestamps.copy()
45 global ratecontroller
46 ratecontroller = self.L.context._rate_controller
4647 self.L.close()
4748 os.chdir('/')
4849 print("Removing {}".format(self.dir))