├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ └── codeql-analysis.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── SECURITY.md
├── _config.yml
├── collection
├── Collection.py
└── __init__.py
├── conf
├── __init__.py
└── config.py
├── interfaces
├── __init__.py
└── telegram
│ └── messenger.py
├── main.py
├── miners
├── Miner.py
├── __init__.py
└── imdb
│ ├── ImdbMiner.py
│ └── __init__.py
├── models
├── Model.py
└── __init__.py
├── movie
├── Movie.py
├── Pop.py
└── __init__.py
├── player
├── Player.py
└── __init__.py
├── quiz
├── Quiz.py
├── __init__.py
└── leaderboard.py
├── requirements.txt
├── runtime.txt
├── server
├── Server.py
└── __init__.py
├── session
├── Session.py
└── __init__.py
├── tests
├── .coverage
└── .coveragerc
└── translations
├── babel.cfg
├── cinemonster.pot
├── generate_files.sh
├── generated
├── en
│ └── LC_MESSAGES
│ │ ├── messages.mo
│ │ └── messages.po
├── es
│ └── LC_MESSAGES
│ │ └── messages.po
└── pt_BR
│ └── LC_MESSAGES
│ ├── messages.mo
│ └── messages.po
└── required.py
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Go to '...'
13 | 2. Click on '....'
14 | 3. Scroll down to '....'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Screenshots**
21 | If applicable, add screenshots to help explain your problem.
22 |
23 | **Desktop (please complete the following information):**
24 | - OS: [e.g. iOS]
25 | - Browser [e.g. chrome, safari]
26 | - Version [e.g. 22]
27 |
28 | **Smartphone (please complete the following information):**
29 | - Device: [e.g. iPhone6]
30 | - OS: [e.g. iOS8.1]
31 | - Browser [e.g. stock browser, safari]
32 | - Version [e.g. 22]
33 |
34 | **Additional context**
35 | Add any other context about the problem here.
36 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ master ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ master ]
20 | schedule:
21 | - cron: '26 7 * * 4'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'python' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
37 | # Learn more:
38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
39 |
40 | steps:
41 | - name: Checkout repository
42 | uses: actions/checkout@v2
43 |
44 | # Initializes the CodeQL tools for scanning.
45 | - name: Initialize CodeQL
46 | uses: github/codeql-action/init@v1
47 | with:
48 | languages: ${{ matrix.language }}
49 | # If you wish to specify custom queries, you can do so here or in a config file.
50 | # By default, queries listed here will override any specified in a config file.
51 | # Prefix the list here with "+" to use these queries and those in the config file.
52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
53 |
54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
55 | # If this step fails, then you should remove it and run the build manually (see below)
56 | - name: Autobuild
57 | uses: github/codeql-action/autobuild@v1
58 |
59 | # ℹ️ Command-line programs to run using the OS shell.
60 | # 📚 https://git.io/JvXDl
61 |
62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
63 | # and modify them (or add more) to build your code if your project
64 | # uses a compiled language
65 |
66 | #- run: |
67 | # make bootstrap
68 | # make release
69 |
70 | - name: Perform CodeQL Analysis
71 | uses: github/codeql-action/analyze@v1
72 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/git,linux,macos,python,windows,sublimetext,visualstudiocode
3 | ### Pycharm ###
4 | .idea/
5 |
6 | ### Git ###
7 | # Created by git for backups. To disable backups in Git:
8 | # $ git config --global mergetool.keepBackup false
9 | *.orig
10 |
11 | # Created by git when using merge tools for conflicts
12 | *.BACKUP.*
13 | *.BASE.*
14 | *.LOCAL.*
15 | *.REMOTE.*
16 | *_BACKUP_*.txt
17 | *_BASE_*.txt
18 | *_LOCAL_*.txt
19 | *_REMOTE_*.txt
20 |
21 | ### Linux ###
22 | *~
23 |
24 | # temporary files which can be created if a process still has a handle open of a deleted file
25 | .fuse_hidden*
26 |
27 | # KDE directory preferences
28 | .directory
29 |
30 | # Linux trash folder which might appear on any partition or disk
31 | .Trash-*
32 |
33 | # .nfs files are created when an open file is removed but is still being accessed
34 | .nfs*
35 |
36 | ### macOS ###
37 | # General
38 | .DS_Store
39 | .AppleDouble
40 | .LSOverride
41 |
42 | # Icon must end with two \r
43 | Icon
44 |
45 | # Thumbnails
46 | ._*
47 |
48 | # Files that might appear in the root of a volume
49 | .DocumentRevisions-V100
50 | .fseventsd
51 | .Spotlight-V100
52 | .TemporaryItems
53 | .Trashes
54 | .VolumeIcon.icns
55 | .com.apple.timemachine.donotpresent
56 |
57 | # Directories potentially created on remote AFP share
58 | .AppleDB
59 | .AppleDesktop
60 | Network Trash Folder
61 | Temporary Items
62 | .apdisk
63 |
64 | ### Python ###
65 | # Byte-compiled / optimized / DLL files
66 | __pycache__/
67 | *.py[cod]
68 | *$py.class
69 |
70 | # C extensions
71 | *.so
72 |
73 | # Distribution / packaging
74 | .Python
75 | build/
76 | develop-eggs/
77 | dist/
78 | downloads/
79 | eggs/
80 | .eggs/
81 | lib/
82 | lib64/
83 | parts/
84 | sdist/
85 | var/
86 | wheels/
87 | *.egg-info/
88 | .installed.cfg
89 | *.egg
90 | MANIFEST
91 |
92 | # PyInstaller
93 | # Usually these files are written by a python script from a template
94 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
95 | *.manifest
96 | *.spec
97 |
98 | # Installer logs
99 | pip-log.txt
100 | pip-delete-this-directory.txt
101 |
102 | # Unit test / coverage reports
103 | htmlcov/
104 | .tox/
105 | .nox/
106 | .coverage
107 | .coverage.*
108 | .cache
109 | nosetests.xml
110 | coverage.xml
111 | *.cover
112 | .hypothesis/
113 | .pytest_cache/
114 |
115 | # Translations
116 | *.mo
117 | *.pot
118 |
119 | # Django stuff:
120 | *.log
121 | local_settings.py
122 | db.sqlite3
123 |
124 | # Flask stuff:
125 | instance/
126 | .webassets-cache
127 |
128 | # Scrapy stuff:
129 | .scrapy
130 |
131 | # Sphinx documentation
132 | docs/_build/
133 |
134 | # PyBuilder
135 | target/
136 |
137 | # Jupyter Notebook
138 | .ipynb_checkpoints
139 |
140 | # IPython
141 | profile_default/
142 | ipython_config.py
143 |
144 | # pyenv
145 | .python-version
146 |
147 | # celery beat schedule file
148 | celerybeat-schedule
149 |
150 | # SageMath parsed files
151 | *.sage.py
152 |
153 | # Environments
154 | .env
155 | .venv
156 | env/
157 | venv/
158 | ENV/
159 | env.bak/
160 | venv.bak/
161 |
162 | # Spyder project settings
163 | .spyderproject
164 | .spyproject
165 |
166 | # Rope project settings
167 | .ropeproject
168 |
169 | # mkdocs documentation
170 | /site
171 |
172 | # mypy
173 | .mypy_cache/
174 | .dmypy.json
175 | dmypy.json
176 |
177 | ## Python Pipenv
178 | Pipfile
179 | Pipfile.lock
180 |
181 | ### Python Patch ###
182 | .venv/
183 |
184 | ### Python.VirtualEnv Stack ###
185 | # Virtualenv
186 | # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
187 | [Bb]in
188 | [Ii]nclude
189 | [Ll]ib
190 | [Ll]ib64
191 | [Ll]ocal
192 | [Ss]cripts
193 | pyvenv.cfg
194 | pip-selfcheck.json
195 |
196 | ### SublimeText ###
197 | # Cache files for Sublime Text
198 | *.tmlanguage.cache
199 | *.tmPreferences.cache
200 | *.stTheme.cache
201 |
202 | # Workspace files are user-specific
203 | *.sublime-workspace
204 |
205 | # Project files should be checked into the repository, unless a significant
206 | # proportion of contributors will probably not be using Sublime Text
207 | # *.sublime-project
208 |
209 | # SFTP configuration file
210 | sftp-config.json
211 |
212 | # Package control specific files
213 | Package Control.last-run
214 | Package Control.ca-list
215 | Package Control.ca-bundle
216 | Package Control.system-ca-bundle
217 | Package Control.cache/
218 | Package Control.ca-certs/
219 | Package Control.merged-ca-bundle
220 | Package Control.user-ca-bundle
221 | oscrypto-ca-bundle.crt
222 | bh_unicode_properties.cache
223 |
224 | # Sublime-github package stores a github token in this file
225 | # https://packagecontrol.io/packages/sublime-github
226 | GitHub.sublime-settings
227 |
228 | ### VisualStudioCode ###
229 | .vscode/
230 |
231 | ### Windows ###
232 | # Windows thumbnail cache files
233 | Thumbs.db
234 | ehthumbs.db
235 | ehthumbs_vista.db
236 |
237 | # Dump file
238 | *.stackdump
239 |
240 | # Folder config file
241 | [Dd]esktop.ini
242 |
243 | # Recycle Bin used on file shares
244 | $RECYCLE.BIN/
245 |
246 | # Windows Installer files
247 | *.cab
248 | *.msi
249 | *.msix
250 | *.msm
251 | *.msp
252 |
253 | # Windows shortcuts
254 | *.lnk
255 |
256 |
257 | # End of https://www.gitignore.io/api/git,linux,macos,python,windows,sublimetext,visualstudiocode
258 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at edward@roguefairy.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to CineMonster
2 |
3 | CineMonster was created with movies fans in mind, so you can improve
4 | this game-type quiz with your tests or coding:
5 |
6 |
7 | # Imagining The Features
8 |
9 | - First imagine what type of trivia you play with your friends, can we put this on
10 | cinemonster ?
11 | - This works with small group of players ?
12 | - This works with major number of players ?
13 | - How can i measure the points of players ?
14 |
15 | If you have affirmatively know something cool based on these question above, please
16 | feel free to request with a issue [here](https://github.com/toymak3r/CineMonster/issues).
17 |
18 | # Coding
19 |
20 | Are you a python developer ? Nice!
21 | Just clone the repository and make improvents, and please, submit your pullrequest here.
22 |
23 | Some important points:
24 | - Focus on respect PEPs([Python Enhancement Proposals](https://www.python.org/dev/peps/))
25 | - Follow good programming practices
26 | - Follow [K.I.S.S](http://people.apache.org/~fhanik/kiss.html) Principle
27 |
28 | # HAVE FUN!
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | -[](https://codeclimate.com/github/toymak3r/CineMonster)
2 | -[](https://codeclimate.com/github/toymak3r/CineMonster/coverage)
3 | -[](https://codeclimate.com/github/toymak3r/CineMonster)
4 |
5 | ## CineMonster
6 | Telegram Bot Quiz About Series and Movies
7 |
8 | ## Information
9 | You can see it running, just add this bot to your group: [cinemonster](http://telegram.me/cinequizbot)
10 |
11 | ## Running your Bot
12 | 1. Configure by editing the config.py on /conf directory (don't forget to add your bot key)
13 | 2. python main.py
14 | 3. Add bot to your group
15 | 4. Type /roll (randomize movies from all decades) or /roll pop ( the top 250 movies from IMDB )
16 | 5. Type /leaderboard to see your ranking
17 | 6. Have fun!
18 |
19 | That's it!
20 |
21 | ## Thanks to:
22 | * [Python-Telegram-Bot](https://github.com/python-telegram-bot/python-telegram-bot)
23 | * [IMDBpie](https://github.com/richardasaurus/imdb-pie)
24 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Use this section to tell people about which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 5.1.x | :white_check_mark: |
11 | | 5.0.x | :x: |
12 | | 4.0.x | :white_check_mark: |
13 | | < 4.0 | :x: |
14 |
15 | ## Reporting a Vulnerability
16 |
17 | Use this section to tell people how to report a vulnerability.
18 |
19 | Tell them where to go, how often they can expect to get an update on a
20 | reported vulnerability, what to expect if the vulnerability is accepted or
21 | declined, etc.
22 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-slate
--------------------------------------------------------------------------------
/collection/Collection.py:
--------------------------------------------------------------------------------
1 | # -------------------------------------------
2 | # CineMonster - A Quiz Bot for Telegram About Series and Movies
3 | # @author: Edward "Toy" Facundo
4 | # @site: http://github.com/toymak3r
5 | # -------------------------------------------
6 | # Collection Class
7 | # -------------------------------------------
8 |
9 |
10 | from miners import Miner
11 | from random import *
12 |
13 |
14 | class Collection:
15 |
16 | movie_list = ''
17 |
18 | def __init__(self, miner, type):
19 | self.miner = miner
20 | self.type = type
21 |
22 | def top_250(self):
23 | self.movie_list = self.miner.top_list(250)
24 |
25 | def general(self):
26 | pass
27 |
28 | def get_rand_movie(self):
29 | movie = None
30 | while movie is None:
31 | if self.type is None:
32 | number = str(randrange(1, 99999))
33 | if len(number) < 7:
34 | number = '0' * (7 - len(number)) + number
35 | movie_id = "tt" + number # formatting to IMDB_ID
36 | else:
37 | self.top_250()
38 | number = randrange(0, len(self.movie_list) - 1)
39 | movie_id = self.movie_list[number]['tconst']
40 |
41 | images, movie = self.miner.get_movie_by_id(movie_id)
42 | print(movie['base']['title'])
43 | if images is not None:
44 | if images['totalImageCount'] < 1:
45 | movie = None
46 |
47 | return movie, images
48 |
--------------------------------------------------------------------------------
/collection/__init__.py:
--------------------------------------------------------------------------------
1 | from collection.Collection import Collection
2 |
--------------------------------------------------------------------------------
/conf/__init__.py:
--------------------------------------------------------------------------------
1 | from conf.config import Config, ProductionConfig, DevelopmentConfig, TestingConfig
2 |
--------------------------------------------------------------------------------
/conf/config.py:
--------------------------------------------------------------------------------
1 | # -------------------------------------------
2 | # CineMonster - A Quiz Bot for Telegram About Series and Movies
3 | # @author: Edward "Toy" Facundo
4 | # @site: http://github.com/toymak3r
5 | # -------------------------------------------
6 |
7 | import os
8 |
9 |
10 | class Config(object):
11 | DEBUG = False
12 | TESTING = False
13 | DATABASE_URI = 'sqlite://:memory:'
14 | TELEGRAM_BOT_KEY = os.environ.get('CINEMONSTER_TELEGRAM_API_KEY')
15 | LOG_FILE = 'cinemonster.log'
16 | QUIZ_LANG = 'en'
17 |
18 |
19 | class ProductionConfig(Config):
20 | DATABASE_URI = 'mysql://user@localhost/foo'
21 | SESSION_EXPIRATION_TIME = 30 # seconds
22 |
23 |
24 | class DevelopmentConfig(Config):
25 | DEBUG = True
26 | SESSION_EXPIRATION_TIME = 10 # seconds
27 |
28 |
29 | class TestingConfig(Config):
30 | TESTING = True
31 |
--------------------------------------------------------------------------------
/interfaces/__init__.py:
--------------------------------------------------------------------------------
1 | from interfaces.telegram.messenger import Messenger as TelegramMessenger
2 |
--------------------------------------------------------------------------------
/interfaces/telegram/messenger.py:
--------------------------------------------------------------------------------
1 | import telegram.ext
2 |
3 |
4 | class Messenger:
5 | bot = ''
6 | formats = {
7 | 'regular': ">* %s *",
8 | 'caption': ">* %s *<",
9 | 'title': "=+= * %s * =+=",
10 | 'highlights': "--+ %s +--",
11 | 'bold': "* %s * %s"
12 | }
13 |
14 | def __init__(self, bot, logger):
15 | self.logger = logger
16 | self.logger.debug(" Started... ")
17 | self.bot = bot
18 |
19 | def send_msg(self, chat_id, msg, type_msg='regular'):
20 | # TODO: trycat this
21 | msg = self.format(type_msg, msg)
22 | self.bot.send_message(chat_id=chat_id,
23 | text=msg,
24 | parse_mode=telegram.ParseMode.MARKDOWN)
25 |
26 | def format(self, type_msg, msg):
27 | return self.formats[type_msg] % msg
28 |
29 | def send_photo(self, chat_id, photo, caption):
30 | # TODO: trycat this
31 | self.bot.send_photo(chat_id=chat_id,
32 | photo=photo,
33 | caption=caption)
34 |
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | # -------------------------------------------
2 | # CineMonster - A Quiz Bot for Telegram About Series and Movies
3 | # @author: Edward "Toy" Facundo
4 | # @site: http://edwardfacundo.wordpress.com
5 | # -------------------------------------------
6 |
7 | import server
8 |
9 |
10 | def main():
11 | server.Server()
12 |
13 |
14 | if __name__ == '__main__':
15 | main()
16 |
--------------------------------------------------------------------------------
/miners/Miner.py:
--------------------------------------------------------------------------------
1 | # -------------------------------------------
2 | # CineMonster - A Quiz Bot for Telegram About Series and Movies
3 | # @author: Edward "Toy" Facundo
4 | # @site: http://github.com/toymak3r
5 | # -------------------------------------------
6 |
7 | from abc import ABCMeta, abstractmethod
8 |
9 |
10 | class Miner(object):
11 |
12 | __metaclass__ = ABCMeta
13 |
14 | handle = None
15 |
16 | @abstractmethod
17 | def top_list(self, number): pass
18 |
19 | @abstractmethod
20 | def get_movie_id(self, index): pass
21 |
22 | @abstractmethod
23 | def get_movie_by_id(self, movie_id): pass
24 |
--------------------------------------------------------------------------------
/miners/__init__.py:
--------------------------------------------------------------------------------
1 | from miners.Miner import Miner
2 | from miners.imdb.ImdbMiner import IMDB
3 |
--------------------------------------------------------------------------------
/miners/imdb/ImdbMiner.py:
--------------------------------------------------------------------------------
1 | # -------------------------------------------
2 | # CineMonster - A Quiz Bot for Telegram About Series and Movies
3 | # @author: Edward "Toy" Facundo
4 | # @site: http://github.com/toymak3r
5 | # -------------------------------------------
6 | # IMDB Miner
7 | # -------------------------------------------
8 |
9 | from miners.Miner import Miner
10 | from imdbpie import Imdb
11 |
12 |
13 | class IMDB(Miner):
14 |
15 | def __init__(self):
16 |
17 | self.handle = Imdb()
18 | super(IMDB, self).__init__()
19 |
20 | def top_list(self, number):
21 | pop_movies = self.handle.top_250()
22 | return pop_movies
23 |
24 | def get_movie_id(self, index):
25 | return "tt" + index # formatting to IMDB_ID
26 |
27 | def get_movie_by_id(self, movie_id):
28 | return self.handle.get_title_images(movie_id), self.handle.get_title(movie_id)
29 |
--------------------------------------------------------------------------------
/miners/imdb/__init__.py:
--------------------------------------------------------------------------------
1 | from miners.imdb.ImdbMiner import IMDB
2 |
--------------------------------------------------------------------------------
/models/Model.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import datetime
4 |
5 | from sqlalchemy import Column, ForeignKey, Integer, String, DateTime
6 | from sqlalchemy.ext.declarative import declarative_base
7 | from sqlalchemy.orm import relationship
8 | from sqlalchemy import create_engine
9 |
10 | Base = declarative_base()
11 |
12 |
13 | class Player(Base):
14 | __tablename__ = 'player'
15 | id = Column(Integer, primary_key=True)
16 | telegram_uid = Column(String(250), nullable=True)
17 | email = Column(String(250), nullable=True)
18 | phone = Column(String(30), nullable=True)
19 |
20 |
21 | class Group(Base):
22 | __tablename__ = 'group'
23 | id = Column(Integer, primary_key=True)
24 | name = Column(String(250), primary_key=True)
25 | player_id = Column(Integer, ForeignKey('player.id'))
26 | points = Column(Integer, nullable=True)
27 | player = relationship(Player)
28 |
29 |
30 | class Session(Base):
31 | __tablename__ = 'session'
32 | id = Column(Integer, primary_key=True)
33 | group_id = Column(Integer, ForeignKey('group.id'))
34 | group = relationship(Group)
35 | started = Column(DateTime, default=datetime.datetime.utcnow)
36 | ended = Column(DateTime)
37 |
38 |
39 | # Create an engine that stores data in the local directory's
40 | # sqlalchemy_example.db file.
41 | engine = create_engine('sqlite:///cinemonster.db')
42 |
43 | # Create all tables in the engine. This is equivalent to "Create Table"
44 | # statements in raw SQL.
45 | Base.metadata.create_all(engine)
46 |
--------------------------------------------------------------------------------
/models/__init__.py:
--------------------------------------------------------------------------------
1 | from models.Model import Player, Group, Session, engine
2 |
--------------------------------------------------------------------------------
/movie/Movie.py:
--------------------------------------------------------------------------------
1 | # -------------------------------------------
2 | # CineMonster - A Quiz Bot for Telegram About Series and Movies
3 | # @author: Edward "Toy" Facundo
4 | # @site: http://github.com/toymak3r
5 | # -------------------------------------------
6 |
7 | from abc import ABCMeta, abstractmethod
8 |
9 |
10 | class Movie(object):
11 |
12 | __metaclass__ = ABCMeta
13 |
14 | id = 0
15 | name = '' # Movie Name
16 | type = '' # Movie Genre
17 |
18 | @abstractmethod
19 | def __init__(self, type):
20 | self.type
21 |
22 | def name(self):
23 | return self.name
24 |
--------------------------------------------------------------------------------
/movie/Pop.py:
--------------------------------------------------------------------------------
1 | # -------------------------------------------
2 | # CineMonster - A Quiz Bot for Telegram About Series and Movies
3 | # @author: Edward "Toy" Facundo
4 | # @site: http://github.com/toymak3r
5 | # -------------------------------------------
6 |
7 | from movie.Movie import Movie
8 |
9 |
10 | class Pop(Movie):
11 |
12 | def __init__(self):
13 | self.type = "pop"
14 |
--------------------------------------------------------------------------------
/movie/__init__.py:
--------------------------------------------------------------------------------
1 | from movie.Movie import Movie
2 | from movie.Pop import Pop
3 |
--------------------------------------------------------------------------------
/player/Player.py:
--------------------------------------------------------------------------------
1 | # -------------------------------------------
2 | # CineMonster - A Quiz Bot for Telegram About Series and Movies
3 | # @author: Edward "Toy" Facundo
4 | # @site: http://edwardfacundo.wordpress.com
5 | # -------------------------------------------
6 |
7 |
8 | class Player:
9 | id = ''
10 | points = 0
11 | name = ''
12 |
13 | def __init__(self, uid):
14 | self.id = uid
15 |
16 | def get_points(self):
17 | return self.points
18 |
19 | def set_name(self, name):
20 | self.name = name
21 |
22 | def add_points(self, points):
23 | self.points += points
24 |
--------------------------------------------------------------------------------
/player/__init__.py:
--------------------------------------------------------------------------------
1 | from player.Player import Player
2 |
--------------------------------------------------------------------------------
/quiz/Quiz.py:
--------------------------------------------------------------------------------
1 | # -------------------------------------------
2 | # CineMonster - A Quiz Bot for Telegram About Series and Movies
3 | # @author: Edward "Toy" Facundo
4 | # @site: http://edwardfacundo.wordpress.com
5 | # -------------------------------------------
6 |
7 | from player.Player import Player
8 | from random import choice
9 | from collection.Collection import Collection
10 | from miners.imdb.ImdbMiner import IMDB
11 |
12 |
13 | class Quiz:
14 | movies_type = ''
15 | movie = None
16 | images = None
17 |
18 | def __init__(self, session):
19 | self.miner = IMDB()
20 | self.session = session
21 |
22 | def set_level(self, level):
23 | pass
24 |
25 | def rand_movie(self, rand_type=None):
26 | movie_id = ''
27 | collection = Collection(self.miner, rand_type)
28 | self.movie, self.images = collection.get_rand_movie()
29 |
30 | def get_movie_photo(self):
31 | try:
32 | return choice(self.images['images'])['url']
33 | except ValueError as e:
34 | raise e
35 |
36 | def get_question(self, rand_type=None):
37 | try:
38 | self.rand_movie(rand_type)
39 | return self.get_movie_photo()
40 | except ValueError as e:
41 | raise(_("not_possible_find_movie"))
42 |
43 | def show(self, update, rand_type):
44 | chat_id = update.message.chat_id
45 | movie_img = self.get_question(rand_type)
46 | self.session.messenger.send_msg(chat_id, "CINEMONSTER", "title")
47 | self.session.messenger.send_photo(
48 | chat_id, movie_img, caption=_("question_which_movie"))
49 | self.session.update_counter()
50 | self.session.status = "running"
51 |
52 | def check_resps(self, update):
53 | chat_id = update.message.chat_id
54 | if str.lower(self.movie['base']['title']) == str.lower(update.message.text):
55 | player = Player(update.message.from_user.id)
56 | player.name = update.message.from_user.first_name + \
57 | " "+update.message.from_user.last_name
58 | try:
59 | self.session.player_add(player)
60 | except ValueError as e:
61 | pass
62 | self.session.players[update.message.from_user.id].add_points(1)
63 | self.session.messenger.send_msg(chat_id,
64 | msg=(player.name, _(
65 | "correct_answer")),
66 | type_msg='bold')
67 | self.movie = None
68 | self.session.status = "stopped"
69 |
70 | def check_expiration(self):
71 | try:
72 | self.session.update_timer()
73 | except ValueError as e:
74 | pass
75 | if self.session.status == "timed_out":
76 | self.session.messenger.send_msg(chat_id=self.session.chat_id,
77 | msg=(_("times_up"),
78 | self.movie['base']['title']),
79 | type_msg='bold')
80 | self.session.status = "stopped"
81 | self.movie = None
82 |
--------------------------------------------------------------------------------
/quiz/__init__.py:
--------------------------------------------------------------------------------
1 | from quiz.Quiz import Quiz
2 |
--------------------------------------------------------------------------------
/quiz/leaderboard.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FromAbyssStudio/CineMonster/7d1188f1f0f8f8e250522e91e9b2870db9b46020/quiz/leaderboard.py
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | assert-exists==0.0.12
2 | Babel==2.9.1
3 | CacheControl==0.11.6
4 | caller-module==0.0.16
5 | certifi==2022.12.7
6 | chardet==3.0.4
7 | coverage==4.5.1
8 | fullpath==0.0.10
9 | future==0.15.2
10 | getclass==0.0.13
11 | i18n==0.2
12 | idna==2.7
13 | imdbpie==4.0.2
14 | isclassmethod==0.0.8
15 | isstaticmethod==0.0.9
16 | isstring==0.0.9
17 | lockfile==0.12.2
18 | objectname==0.0.8
19 | public==0.0.33
20 | py==1.10.0
21 | python-telegram-bot==4.2.1
22 | pytz==2016.4
23 | requests==2.20.0
24 | six==1.10.0
25 | SQLAlchemy==1.0.13
26 | telegram==0.0.1
27 | tolist==0.0.11
28 | urllib3==1.26.5
29 |
--------------------------------------------------------------------------------
/runtime.txt:
--------------------------------------------------------------------------------
1 | python-3.5.1
2 |
--------------------------------------------------------------------------------
/server/Server.py:
--------------------------------------------------------------------------------
1 | # -------------------------------------------
2 | # CineMonster - A Quiz Bot for Telegram About Series and Movies
3 | # @author: Edward "Toy" Facundo
4 | # @site: http://edwardfacundo.wordpress.com
5 | # -------------------------------------------
6 |
7 | import logging
8 | from translations.required import *
9 | from argparse import ArgumentParser
10 | from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
11 |
12 | import conf
13 | import interfaces
14 | import session
15 | import quiz
16 | import player
17 |
18 |
19 | class Server:
20 | logger = logging.getLogger(__name__)
21 | SESSIONS = dict()
22 |
23 | def __init__(self):
24 | self.config_instance = self.config_init()
25 | updater = Updater(self.config_instance.TELEGRAM_BOT_KEY)
26 | dp = updater.dispatcher
27 |
28 | logging.basicConfig(
29 | format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
30 | filename=self.config_instance.LOG_FILE
31 | )
32 |
33 | dp.add_handler(MessageHandler(
34 | [Filters.text], self.command_check_resps))
35 | dp.add_handler(CommandHandler("start", self.command_start))
36 | dp.add_handler(CommandHandler(
37 | "roll", self.command_roll, pass_args=True))
38 | dp.add_handler(CommandHandler("leaderboard", self.command_leaderboard))
39 | dp.add_error_handler(self.error)
40 |
41 | jq = updater.job_queue
42 | jq.put(self.update_all_timers, 1)
43 |
44 | self.logger.info("Started... ")
45 |
46 | updater.start_polling()
47 | updater.idle()
48 |
49 | def config_init(self):
50 | arg_parser = ArgumentParser(description="CineMonster Telegram Bot")
51 |
52 | arg_parser.add_argument("-e", "--env", metavar='env', type=str, default="prod",
53 | help="environment to run: dev, test or prod")
54 |
55 | arg_parser.add_argument("-v", "--verbose", metavar='verbose', type=bool, default=False,
56 | help="print information about running bot")
57 |
58 | args = arg_parser.parse_args()
59 |
60 | if args.env == "prod":
61 | return conf.ProductionConfig
62 | elif args.env == "dev":
63 | return conf.DevelopmentConfig
64 | else:
65 | return conf.TestingConfig
66 |
67 | def error(self, update, error):
68 | self.logger.warning('Update "%s" caused error "%s"' % (update, error))
69 |
70 | def update_all_timers(self, bot):
71 | for session in self.SESSIONS:
72 | self.SESSIONS[session].update_timer()
73 | self.SESSIONS[session].quiz.check_expiration()
74 |
75 | def command_start(self, bot, update):
76 | chat_id = update.message.chat_id
77 | if chat_id not in self.SESSIONS.keys():
78 | self.messenger = interfaces.TelegramMessenger(bot, self.logger)
79 | self.SESSIONS[chat_id] = session.Session(
80 | chat_id, self.config_instance, self.logger)
81 | self.SESSIONS[chat_id].set_messenger(self.messenger)
82 | self.SESSIONS[chat_id].quiz = quiz.Quiz(self.SESSIONS[chat_id])
83 |
84 | def command_roll(self, bot, update, args=''):
85 | chat_id = update.message.chat_id
86 | rand_type = args is None and args[0] or None
87 | self.SESSIONS[chat_id].messenger.send_msg(
88 | chat_id, _("searching_movies"))
89 | self.SESSIONS[chat_id].quiz.show(update, rand_type)
90 |
91 | def command_leaderboard(self, bot, update):
92 | chat_id = update.message.chat_id
93 | session = self.SESSIONS[chat_id]
94 | try:
95 | session.messenger.send_msg(chat_id, _(
96 | "leader_board_title"), 'highlights')
97 | ldb = session.get_leaderboard()
98 | session.messenger.send_msg(chat_id, ldb)
99 | except ValueError as e:
100 | session.messenger.send_msg(
101 | chat_id, update.message.from_user.first_name + e.args[0])
102 |
103 | def command_action(self, bot, update):
104 | group = update.message.chat_id
105 | try:
106 | player = player.Player(update.message.from_user.id)
107 | player.name = update.message.from_user.first_name + \
108 | " " + update.message.from_user.last_name
109 | self.SESSIONS[group].player_add(player)
110 | self.SESSIONS[update.message.chat_id].messenger.send(
111 | update, player.name + _(" joined_the_game"))
112 | except ValueError as e:
113 | self.SESSIONS[update.message.chat_id].messenger.send(
114 | update, update.message.from_user.first_name + e.args[0])
115 |
116 | def command_repeat(self, bot, update):
117 | movie_img = self.SESSIONS[update.message.chat_id].quiz.get_question()
118 | self.SESSIONS[update.message.chat_id].messenger.send(
119 | update, _("repeating"))
120 | bot.send_photo(chat_id=update.message.chat_id,
121 | photo=movie_img, caption=_("what_is_the_movie_series_name"))
122 | self.SESSIONS[update.message.chat_id].messenger.send(
123 | update, "===========================")
124 |
125 | def command_cut(self, bot, update):
126 | group = update.message.chat_id
127 | try:
128 | player = player.Player(update.message.from_user.id)
129 | self.SESSIONS[group].player_quit(player)
130 | self.SESSIONS[update.message.chat_id].messenger.send(update,
131 | update.message.from_user.first_name + _("_left_the_game!"))
132 | except ValueError as e:
133 | self.SESSIONS[update.message.chat_id].messenger.send(
134 | update, update.message.from_user.first_name + e.args[0])
135 |
136 | def command_stop(self, bot, update):
137 | try:
138 | del (self.SESSIONS[update.message.chat_id])
139 | self.SESSIONS[update.message.chat_id].messenger.send(
140 | update, _("ending_the_game"))
141 | except ValueError as e:
142 | self.SESSIONS[update.message.chat_id].messenger.send(
143 | update, _("game_was_not_finished") + e)
144 |
145 | def command_check_resps(self, bot, update):
146 | self.SESSIONS[update.message.chat_id].quiz.check_resps(update)
147 |
--------------------------------------------------------------------------------
/server/__init__.py:
--------------------------------------------------------------------------------
1 | from server.Server import Server
2 |
--------------------------------------------------------------------------------
/session/Session.py:
--------------------------------------------------------------------------------
1 | # -------------------------------------------
2 | # CineMonster - A Quiz Bot for Telegram About Series and Movies
3 | # @author: Edward "Toy" Facundo
4 | # @site: http://edwardfacundo.wordpress.com
5 | # -------------------------------------------
6 |
7 | import datetime
8 | import time
9 |
10 |
11 | class Session:
12 | quiz = ''
13 | players = dict()
14 | started = ''
15 | ended = ''
16 | status = ''
17 | messenger = ''
18 | bot = ''
19 | expiration = 30 # default
20 | counter = 0
21 | chat_id = 0
22 | config = ''
23 |
24 | def __init__(self, chat_id, config, logger):
25 | self.logger = logger
26 | self.started = datetime.datetime.utcnow()
27 | self.chat_id = chat_id
28 | self.config = config
29 | self.expiration = self.config.SESSION_EXPIRATION_TIME
30 |
31 | def player_add(self, player):
32 | if player.id not in self.players.keys():
33 | self.players[player.id] = player
34 | else:
35 | self.update_log()
36 | raise ValueError(' já está na partida...')
37 |
38 | def player_quit(self, player):
39 | del(self.players[player.id])
40 |
41 | def end(self):
42 | self.ended = datetime.datetime.utcnow()
43 |
44 | def get_leaderboard(self):
45 | ldb = ''
46 | for x in self.players:
47 | ldb += self.players[x].name+" : " + \
48 | str(self.players[x].get_points())+" \n"
49 | return ldb
50 |
51 | def set_messenger(self, messenger):
52 | self.messenger = messenger
53 |
54 | def update_timer(self):
55 | if self.status == "running":
56 | t = self.update_log()
57 | if t.seconds > self.expiration:
58 | self.status = "timed_out"
59 |
60 | def update_counter(self):
61 | self.counter = datetime.datetime.utcnow()
62 | self.logger.debug(str(self.chat_id)+" : " +
63 | "updater_counter: "+str(self.counter))
64 |
65 | def update_log(self):
66 | t = datetime.datetime.utcnow() - self.counter
67 | self.logger.debug(str(self.chat_id) + " : " +
68 | "updater_timer: " + str(t))
69 | return t
70 |
--------------------------------------------------------------------------------
/session/__init__.py:
--------------------------------------------------------------------------------
1 | from session.Session import Session
2 |
--------------------------------------------------------------------------------
/tests/.coverage:
--------------------------------------------------------------------------------
1 | !coverage.py: This is a private format, don't read it directly!{"lines":{"/data/home/toy/devel/cinemonster/main.py":[8,10,11,12,13,14,15,16,17,18,20,23,26,29,58,78,82,89,90,33,60,62,63,65,66,68,70,71,35,36,38,39,40,43,44,45,46,47,49,50,52,54,55,84],"/data/home/toy/devel/cinemonster/translations/required.py":[1,4,5,7],"/data/home/toy/devel/cinemonster/conf/config.py":[9,10,11,12,13,14,15,17,18,19,22,23,24,27,28],"/data/home/toy/devel/cinemonster/session.py":[8,9,10,13,14,15,16,17,18,19,20,21,22,23,24,26,33,40,43,46,52,55,62],"/data/home/toy/devel/cinemonster/quiz.py":[8,9,10,11,12,15,16,17,18,20,25,28,48,54,61,69,84],"/data/home/toy/devel/cinemonster/player.py":[8,9,10,11,13,16,19,22],"/data/home/toy/devel/cinemonster/messenger.py":[1,4,5,7,8,9,10,11,14,19,26,29],"/data/home/toy/devel/cinemonster/commands.py":[2,12,20,32,44,52,64,73]}}
--------------------------------------------------------------------------------
/tests/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | omit = */.env/*
3 |
--------------------------------------------------------------------------------
/translations/babel.cfg:
--------------------------------------------------------------------------------
1 | [python: **.py]
2 |
--------------------------------------------------------------------------------
/translations/cinemonster.pot:
--------------------------------------------------------------------------------
1 | # Translations template for PROJECT.
2 | # Copyright (C) 2018 ORGANIZATION
3 | # This file is distributed under the same license as the PROJECT project.
4 | # FIRST AUTHOR , 2018.
5 | #
6 | #, fuzzy
7 | msgid ""
8 | msgstr ""
9 | "Project-Id-Version: PROJECT VERSION\n"
10 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
11 | "POT-Creation-Date: 2018-10-18 14:35+0200\n"
12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 | "Last-Translator: FULL NAME \n"
14 | "Language-Team: LANGUAGE \n"
15 | "MIME-Version: 1.0\n"
16 | "Content-Type: text/plain; charset=utf-8\n"
17 | "Content-Transfer-Encoding: 8bit\n"
18 | "Generated-By: Babel 2.6.0\n"
19 |
20 |
21 | #: ../quiz/Quiz.py:41
22 | msgid "not_possible_find_movie"
23 | msgstr ""
24 |
25 | #: ../quiz/Quiz.py:48
26 | msgid "question_which_movie"
27 | msgstr ""
28 |
29 | #: ../quiz/Quiz.py:64
30 | msgid "correct_answer"
31 | msgstr ""
32 |
33 | #: ../quiz/Quiz.py:77
34 | msgid "times_up"
35 | msgstr ""
36 |
37 | #: ../server/Server.py:88
38 | msgid "searching_movies"
39 | msgstr ""
40 |
41 | #: ../server/Server.py:95
42 | msgid "leader_board_title"
43 | msgstr ""
44 |
45 | #: ../server/Server.py:111
46 | msgid " joined_the_game"
47 | msgstr ""
48 |
49 | #: ../server/Server.py:119
50 | msgid "repeating"
51 | msgstr ""
52 |
53 | #: ../server/Server.py:121
54 | msgid "what_is_the_movie_series_name"
55 | msgstr ""
56 |
57 | #: ../server/Server.py:131
58 | msgid "_left_the_game!"
59 | msgstr ""
60 |
61 | #: ../server/Server.py:140
62 | msgid "ending_the_game"
63 | msgstr ""
64 |
65 | #: ../server/Server.py:143
66 | msgid "game_was_not_finished"
67 | msgstr ""
68 |
69 |
--------------------------------------------------------------------------------
/translations/generate_files.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Script for Generate Translation files
3 | # @author: Edward "Toy" Facundo
4 | # requires: pybabel
5 |
6 | TRANSLATION_DIR=./
7 | LANGS=("pt_BR" "en" "es") # todo: smarter detection
8 | GENERATED_DIR=./generated
9 | options=("create" "update" "compile" "clean" "quit")
10 | select opt in "${options[@]}"
11 | do
12 | case $opt in
13 | "create")
14 | echo "Creating files"
15 | pybabel extract -F babel.cfg -o cinemonster.pot ../
16 | for lang in ${LANGS[@]}; do
17 | pybabel init -i cinemonster.pot -d "${GENERATED_DIR}" -l ${lang};
18 | done
19 | ;;
20 | "update")
21 | echo "updating files"
22 | pybabel update -i cinemonster.pot --previous -d "${GENERATED_DIR}"
23 | ;;
24 | "compile")
25 | echo "compiling files"
26 | pybabel compile -d "${GENERATED_DIR}"
27 | ;;
28 | "clean")
29 | echo "cleaning files"
30 | rm -rf "${GENERATED_DIR}"
31 | rm cinemonster.pot
32 | ;;
33 | "quit")
34 | break
35 | ;;
36 | *) echo invalid option;;
37 | esac
38 | done
39 |
--------------------------------------------------------------------------------
/translations/generated/en/LC_MESSAGES/messages.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FromAbyssStudio/CineMonster/7d1188f1f0f8f8e250522e91e9b2870db9b46020/translations/generated/en/LC_MESSAGES/messages.mo
--------------------------------------------------------------------------------
/translations/generated/en/LC_MESSAGES/messages.po:
--------------------------------------------------------------------------------
1 | # English translations for PROJECT.
2 | # Copyright (C) 2018 ORGANIZATION
3 | # This file is distributed under the same license as the PROJECT project.
4 | # FIRST AUTHOR , 2018.
5 | #
6 | msgid ""
7 | msgstr ""
8 | "Project-Id-Version: PROJECT VERSION\n"
9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
10 | "POT-Creation-Date: 2018-10-18 14:35+0200\n"
11 | "PO-Revision-Date: 2018-10-18 14:35+0200\n"
12 | "Last-Translator: FULL NAME \n"
13 | "Language: en\n"
14 | "Language-Team: en \n"
15 | "Plural-Forms: nplurals=2; plural=(n != 1)\n"
16 | "MIME-Version: 1.0\n"
17 | "Content-Type: text/plain; charset=utf-8\n"
18 | "Content-Transfer-Encoding: 8bit\n"
19 | "Generated-By: Babel 2.6.0\n"
20 |
21 | #: ../quiz/Quiz.py:41
22 | msgid "not_possible_find_movie"
23 | msgstr ""
24 |
25 | #: ../quiz/Quiz.py:48
26 | msgid "question_which_movie"
27 | msgstr ""
28 |
29 | #: ../quiz/Quiz.py:64
30 | msgid "correct_answer"
31 | msgstr ""
32 |
33 | #: ../quiz/Quiz.py:77
34 | msgid "times_up"
35 | msgstr ""
36 |
37 | #: ../server/Server.py:88
38 | msgid "searching_movies"
39 | msgstr ""
40 |
41 | #: ../server/Server.py:95
42 | msgid "leader_board_title"
43 | msgstr ""
44 |
45 | #: ../server/Server.py:111
46 | msgid " joined_the_game"
47 | msgstr ""
48 |
49 | #: ../server/Server.py:119
50 | msgid "repeating"
51 | msgstr ""
52 |
53 | #: ../server/Server.py:121
54 | msgid "what_is_the_movie_series_name"
55 | msgstr ""
56 |
57 | #: ../server/Server.py:131
58 | msgid "_left_the_game!"
59 | msgstr ""
60 |
61 | #: ../server/Server.py:140
62 | msgid "ending_the_game"
63 | msgstr ""
64 |
65 | #: ../server/Server.py:143
66 | msgid "game_was_not_finished"
67 | msgstr ""
68 |
--------------------------------------------------------------------------------
/translations/generated/es/LC_MESSAGES/messages.po:
--------------------------------------------------------------------------------
1 | # Spanish translations for PROJECT.
2 | # Copyright (C) 2018 ORGANIZATION
3 | # This file is distributed under the same license as the PROJECT project.
4 | #
5 | # FIRST AUTHOR , 2018.
6 | # victorhck , 2018.
7 | msgid ""
8 | msgstr ""
9 | "Project-Id-Version: PROJECT VERSION\n"
10 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
11 | "POT-Creation-Date: 2018-10-18 14:35+0200\n"
12 | "PO-Revision-Date: 2018-10-18 14:39+0100\n"
13 | "Last-Translator: victorhck \n"
14 | "Language: es\n"
15 | "Language-Team: Spanish <>\n"
16 | "Plural-Forms: nplurals=2; plural=(n != 1)\n"
17 | "MIME-Version: 1.0\n"
18 | "Content-Type: text/plain; charset=UTF-8\n"
19 | "Content-Transfer-Encoding: 8bit\n"
20 | "Generated-By: Babel 2.6.0\n"
21 | "X-Generator: Lokalize 2.0\n"
22 |
23 | #: ../quiz/Quiz.py:41
24 | msgid "not_possible_find_movie"
25 | msgstr "no fue posible encontrar la película"
26 |
27 | #: ../quiz/Quiz.py:48
28 | msgid "question_which_movie"
29 | msgstr "¿Cual es el nombre de la película?"
30 |
31 | #: ../quiz/Quiz.py:64
32 | msgid "correct_answer"
33 | msgstr "¡Acertaste con la respuesta correcta!"
34 |
35 | #: ../quiz/Quiz.py:77
36 | msgid "times_up"
37 | msgstr ""
38 | "¡Se acabó el tiempo! "
39 | "La respuesta es: "
40 |
41 | #: ../server/Server.py:88
42 | msgid "searching_movies"
43 | msgstr "Buscando películas..."
44 |
45 | #: ../server/Server.py:95
46 | msgid "leader_board_title"
47 | msgstr "Salón de la fama"
48 |
49 | #: ../server/Server.py:111
50 | msgid " joined_the_game"
51 | msgstr ""
52 |
53 | #: ../server/Server.py:119
54 | msgid "repeating"
55 | msgstr ""
56 |
57 | #: ../server/Server.py:121
58 | msgid "what_is_the_movie_series_name"
59 | msgstr ""
60 |
61 | #: ../server/Server.py:131
62 | msgid "_left_the_game!"
63 | msgstr ""
64 |
65 | #: ../server/Server.py:140
66 | msgid "ending_the_game"
67 | msgstr ""
68 |
69 | #: ../server/Server.py:143
70 | msgid "game_was_not_finished"
71 | msgstr ""
--------------------------------------------------------------------------------
/translations/generated/pt_BR/LC_MESSAGES/messages.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FromAbyssStudio/CineMonster/7d1188f1f0f8f8e250522e91e9b2870db9b46020/translations/generated/pt_BR/LC_MESSAGES/messages.mo
--------------------------------------------------------------------------------
/translations/generated/pt_BR/LC_MESSAGES/messages.po:
--------------------------------------------------------------------------------
1 | # Portuguese (Brazil) translations for PROJECT.
2 | # Copyright (C) 2018 ORGANIZATION
3 | # This file is distributed under the same license as the PROJECT project.
4 | # FIRST AUTHOR , 2018.
5 | #
6 | msgid ""
7 | msgstr ""
8 | "Project-Id-Version: PROJECT VERSION\n"
9 | "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
10 | "POT-Creation-Date: 2018-10-18 14:35+0200\n"
11 | "PO-Revision-Date: 2018-10-18 14:35+0200\n"
12 | "Last-Translator: FULL NAME \n"
13 | "Language: pt_BR\n"
14 | "Language-Team: pt_BR \n"
15 | "Plural-Forms: nplurals=2; plural=(n > 1)\n"
16 | "MIME-Version: 1.0\n"
17 | "Content-Type: text/plain; charset=utf-8\n"
18 | "Content-Transfer-Encoding: 8bit\n"
19 | "Generated-By: Babel 2.6.0\n"
20 |
21 | #: ../quiz/Quiz.py:41
22 | msgid "not_possible_find_movie"
23 | msgstr ""
24 |
25 | #: ../quiz/Quiz.py:48
26 | msgid "question_which_movie"
27 | msgstr ""
28 |
29 | #: ../quiz/Quiz.py:64
30 | msgid "correct_answer"
31 | msgstr ""
32 |
33 | #: ../quiz/Quiz.py:77
34 | msgid "times_up"
35 | msgstr ""
36 |
37 | #: ../server/Server.py:88
38 | msgid "searching_movies"
39 | msgstr ""
40 |
41 | #: ../server/Server.py:95
42 | msgid "leader_board_title"
43 | msgstr ""
44 |
45 | #: ../server/Server.py:111
46 | msgid " joined_the_game"
47 | msgstr ""
48 |
49 | #: ../server/Server.py:119
50 | msgid "repeating"
51 | msgstr ""
52 |
53 | #: ../server/Server.py:121
54 | msgid "what_is_the_movie_series_name"
55 | msgstr ""
56 |
57 | #: ../server/Server.py:131
58 | msgid "_left_the_game!"
59 | msgstr ""
60 |
61 | #: ../server/Server.py:140
62 | msgid "ending_the_game"
63 | msgstr ""
64 |
65 | #: ../server/Server.py:143
66 | msgid "game_was_not_finished"
67 | msgstr ""
68 |
--------------------------------------------------------------------------------
/translations/required.py:
--------------------------------------------------------------------------------
1 | import gettext
2 |
3 | """ localization support """
4 | en = gettext.translation(
5 | 'messages', 'translations/generated', languages=['en'])
6 | pt_br = gettext.translation(
7 | 'messages', 'translations/generated', languages=['pt_BR'])
8 |
9 | en.install()
10 |
--------------------------------------------------------------------------------