Compare commits
14
Commits
a246ca69fe
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8400993ad5 | ||
|
|
7222e18811 | ||
|
|
56feecfeff | ||
|
|
6806a878b6 | ||
|
|
73ef4003a8 | ||
|
|
f5e9da7c83 | ||
|
|
27bae3e375 | ||
|
|
a7302d8c2e | ||
|
|
1799f5a3c7 | ||
|
|
1a4405fbbc | ||
|
|
222bf53b25 | ||
|
|
5c16001824 | ||
|
|
7394f88d29 | ||
|
|
df496a8592 |
+30
@@ -0,0 +1,30 @@
|
|||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: python:3.10-alpine
|
||||||
|
commands:
|
||||||
|
- python3 -m pip install --upgrade pip
|
||||||
|
- pip3 install -r requirements.txt
|
||||||
|
- python3 -m pip install --upgrade build
|
||||||
|
- python3 -m build
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- main
|
||||||
|
|
||||||
|
- name: publish
|
||||||
|
image: python:3.10-alpine
|
||||||
|
environment:
|
||||||
|
TWINE_USERNAME:
|
||||||
|
from_secret: PYPI_USERNAME
|
||||||
|
TWINE_PASSWORD:
|
||||||
|
from_secret: PYPI_PASSWORD
|
||||||
|
commands:
|
||||||
|
- python3 -m pip install --upgrade twine
|
||||||
|
- python3 -m twine upload dist/*
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- main
|
||||||
|
|
||||||
+179
@@ -0,0 +1,179 @@
|
|||||||
|
*~
|
||||||
|
.\#*
|
||||||
|
\#*\#
|
||||||
|
.*.~undo-tree~
|
||||||
|
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/python
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=python
|
||||||
|
|
||||||
|
### Python ###
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
### Python Patch ###
|
||||||
|
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
|
||||||
|
poetry.toml
|
||||||
|
|
||||||
|
# ruff
|
||||||
|
.ruff_cache/
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/python
|
||||||
|
|
||||||
@@ -20,3 +20,34 @@
|
|||||||
** 0.5.1 <2022-07-10>
|
** 0.5.1 <2022-07-10>
|
||||||
New feature: download posters and use them as icons for notifications.
|
New feature: download posters and use them as icons for notifications.
|
||||||
New small feature: showing information about a current task.
|
New small feature: showing information about a current task.
|
||||||
|
** 0.5.2 <2022-07-21>
|
||||||
|
Added pyproject.toml.
|
||||||
|
Added img/ folder.
|
||||||
|
** 0.6.0 <2022-08-11>
|
||||||
|
Updated the cli interface
|
||||||
|
** 1.0.1 <2023-01-14>
|
||||||
|
Added TOML configuration file.
|
||||||
|
Updated paths of files and folders.
|
||||||
|
Updated my name to my fullname and release years.
|
||||||
|
** 1.0.2 <2023-01-15>
|
||||||
|
Refactor the database class and remove function for the creating file.
|
||||||
|
** 1.1.1 <2023-02-28>
|
||||||
|
Added os paths for the data and the config by default.
|
||||||
|
Added if config is missing, then the hint shows its path.
|
||||||
|
Updated pyproject.toml information.
|
||||||
|
** 1.1.2 <2023-07-16>
|
||||||
|
Add the requirements and .gitignore.
|
||||||
|
** 1.1.3 <2023-07-16>
|
||||||
|
Update the mail information.
|
||||||
|
** 1.1.4 <2023-07-16>
|
||||||
|
Update the package information and imports.
|
||||||
|
** 1.2.0 <2023-07-16>
|
||||||
|
Add commands to execute the package.
|
||||||
|
** 1.2.1 <2023-07-16>
|
||||||
|
Remove the README.org.
|
||||||
|
** 1.2.2 <2023-07-16>
|
||||||
|
Add the CI/CD configuration.
|
||||||
|
** 1.2.3 <2023-07-16>
|
||||||
|
Fix the command that was "ans", but it must be "asn".
|
||||||
|
** 1.2.4 <2023-07-16>
|
||||||
|
Update the README.
|
||||||
|
|||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
* Anitube Simple Notification
|
|
||||||
Anitube Simple Notification is a application made for getting
|
|
||||||
notification when a content is updated on the web-site
|
|
||||||
(anitube.in.ua).
|
|
||||||
*Not ready for using as applications.*
|
|
||||||
|
|
||||||
* Author
|
|
||||||
Kostya Klochko (c) 2022
|
|
||||||
|
|
||||||
* License
|
|
||||||
Under GNU GPL v3 license
|
|
||||||
+74
@@ -0,0 +1,74 @@
|
|||||||
|
Anitube Simple Notification
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Anitube Simple Notification is a application made for getting
|
||||||
|
notification when a content is updated on the web-site (anitube.in.ua).
|
||||||
|
|
||||||
|
Install
|
||||||
|
=======
|
||||||
|
|
||||||
|
Ensure that python and pip are installed:
|
||||||
|
|
||||||
|
.. code:: shell
|
||||||
|
|
||||||
|
python --version
|
||||||
|
python -m pip -V
|
||||||
|
# or
|
||||||
|
python3 --version
|
||||||
|
python3 -m pip -V
|
||||||
|
|
||||||
|
Install the package:
|
||||||
|
|
||||||
|
.. code:: shell
|
||||||
|
|
||||||
|
pip install anitube-simple-notification
|
||||||
|
# or
|
||||||
|
pip3 install anitube-simple-notification
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
In application folder create file with name ``config.toml``. If a value
|
||||||
|
is wrong, then a error will be shown. If there no value or a wrong value
|
||||||
|
then it will be default.
|
||||||
|
|
||||||
|
Example of a config file for all options:
|
||||||
|
|
||||||
|
.. code:: toml
|
||||||
|
|
||||||
|
POSTERS = true
|
||||||
|
WAITING_PERIOD = 3600
|
||||||
|
URLS = [
|
||||||
|
"https://anitube.in.ua/4110-chainsaw-man.html",
|
||||||
|
"https://anitube.in.ua/4010-overlord-iv.html",
|
||||||
|
"https://anitube.in.ua/4097-mob-varyat-100-3-sezon.html",
|
||||||
|
"https://anitube.in.ua/4087-spy-x-family-part-2.html",
|
||||||
|
]
|
||||||
|
|
||||||
|
The last comma of the urls list can be ommited.
|
||||||
|
|
||||||
|
Run the program by one of the commands:
|
||||||
|
|
||||||
|
.. code:: shell
|
||||||
|
|
||||||
|
anitube-simple-notification
|
||||||
|
asn
|
||||||
|
|
||||||
|
Author
|
||||||
|
======
|
||||||
|
|
||||||
|
Kostiantyn Klochko (c) 2022-2023
|
||||||
|
|
||||||
|
Donation
|
||||||
|
========
|
||||||
|
|
||||||
|
Monero:
|
||||||
|
8BCZr3LaciDZUwNUbC8M5gNZTtnPKoT9cMH95YcBoo2k8sg4qaxejYL4Qvp6V21ViqMHj5sHLiuRwhMYxHTVW1HUNAawV6c
|
||||||
|
|image1|
|
||||||
|
|
||||||
|
License
|
||||||
|
=======
|
||||||
|
|
||||||
|
Under GNU GPL v3 license
|
||||||
|
|
||||||
|
.. |image1| image:: ./img/monero.png
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
@@ -0,0 +1,40 @@
|
|||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=61.0"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "anitube-simple-notification"
|
||||||
|
version = "1.2.4"
|
||||||
|
authors = [
|
||||||
|
{ name="Kostiantyn Klochko", email="kklochko@protonmail.com" },
|
||||||
|
]
|
||||||
|
description = "Getting notification from anitube.in.ua."
|
||||||
|
readme = "README.rst"
|
||||||
|
license = { file="COPYING" }
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
classifiers = [
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
]
|
||||||
|
dependencies = [
|
||||||
|
"requests~=2.28.2",
|
||||||
|
"beautifulsoup4~=4.11.1",
|
||||||
|
"notify-py~=0.3.39",
|
||||||
|
"rich~=13.1.0",
|
||||||
|
"tomli~=2.0.1",
|
||||||
|
"loguru~=0.5.3",
|
||||||
|
"platformdirs~=3.0.0"
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
asn = "src.main:main"
|
||||||
|
anitube-simple-notification = "src.main:main"
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
"Homepage" = "https://gitlab.com/KKlochko/anitube-simple-notification"
|
||||||
|
"Bug Tracker" = "https://gitlab.com/KKlochko/anitube-simple-notification/issues"
|
||||||
|
|
||||||
|
[tool.setuptools]
|
||||||
|
packages = ["src"]
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
beautifulsoup4==4.11.1
|
||||||
|
bs4==0.0.1
|
||||||
|
certifi==2022.12.7
|
||||||
|
charset-normalizer==3.0.1
|
||||||
|
commonmark==0.9.1
|
||||||
|
idna==3.4
|
||||||
|
jeepney==0.8.0
|
||||||
|
loguru==0.5.3
|
||||||
|
notify-py==0.3.39
|
||||||
|
platformdirs==3.0.0
|
||||||
|
Pygments==2.14.0
|
||||||
|
requests==2.28.2
|
||||||
|
rich==13.1.0
|
||||||
|
soupsieve==2.3.2.post1
|
||||||
|
tomli==2.0.1
|
||||||
|
urllib3==1.26.14
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
##########################################################################
|
||||||
|
# Copyright (C) 2022-2023 Kostiantyn Klochko <kklochko@protonmail.com> #
|
||||||
|
# #
|
||||||
|
# This file is part of Anitube Simple Notification. #
|
||||||
|
# #
|
||||||
|
# Anitube Simple Notification is free software: you can redistribute #
|
||||||
|
# it and/or modify it under the terms of the GNU General Public #
|
||||||
|
# License as published by the Free Software Foundation, either version #
|
||||||
|
# 3 of the License, or (at your option) any later version. #
|
||||||
|
# #
|
||||||
|
# Anitube Simple Notification is distributed in the hope that it will #
|
||||||
|
# be useful, but WITHOUT ANY WARRANTY; without even the implied #
|
||||||
|
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See #
|
||||||
|
# the GNU General Public License for more details. #
|
||||||
|
# #
|
||||||
|
# You should have received a copy of the GNU General Public License #
|
||||||
|
# along with Anitube Simple Notification. If not, see #
|
||||||
|
# <https://www.gnu.org/licenses/>. #
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
This module has all for simplify work with the toml configuration file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from rich.console import Console
|
||||||
|
import tomli
|
||||||
|
from pathlib import PosixPath
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
@staticmethod
|
||||||
|
def config_validation(config: dict) -> bool:
|
||||||
|
"""Return False if config is invalid. Empty values is valid."""
|
||||||
|
validations = {
|
||||||
|
"POSTERS": lambda v: isinstance(v, bool),
|
||||||
|
"WAITING_PERIOD": lambda v: isinstance(v, int) and v >= 0,
|
||||||
|
"URLS": lambda l: isinstance(l, list) and len(l) == len(list(filter(str,l))),
|
||||||
|
}
|
||||||
|
return all(validations.get(k, lambda x: False)(v) for (k, v) in config.items())
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def config_validation_detail(config: dict) -> dict:
|
||||||
|
"""Return a dict where key is a field and value is valid status."""
|
||||||
|
validations = {
|
||||||
|
"POSTERS": lambda v: isinstance(v, bool),
|
||||||
|
"WAITING_PERIOD": lambda v: isinstance(v, int) and v >= 0,
|
||||||
|
"URLS": lambda l: isinstance(l, list) and
|
||||||
|
len(list(filter(lambda v: isinstance(v,str), l))) and
|
||||||
|
len(list(filter(lambda v: v.startswith("https://anitube.in.ua/"), l)))
|
||||||
|
#len(l) == len(list(filter(str,l))),
|
||||||
|
}
|
||||||
|
return {k:validations.get(k, lambda x: False)(v) for (k, v) in config.items()}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def config_validation_error(config: dict):
|
||||||
|
"""Show error and remove invalid fields."""
|
||||||
|
validation = Config.config_validation_detail(config)
|
||||||
|
if not validation.pop("POSTERS", True):
|
||||||
|
Console().print(f"[red][ERROR] Please, POSTER must be false or true.[/]")
|
||||||
|
del config["POSTERS"]
|
||||||
|
if not validation.pop("WAITING_PERIOD", True):
|
||||||
|
Console().print(
|
||||||
|
''.join(["[red][ERROR] ",
|
||||||
|
"Please, WAITING_PERIOD must be an integer that greater",
|
||||||
|
"than zero or equals to.[/]"]))
|
||||||
|
del config["WAITING_PERIOD"]
|
||||||
|
if not validation.pop("URLS", True):
|
||||||
|
Console().print(
|
||||||
|
"".join(["[red][ERROR] Please, URLS must be a list of strings"
|
||||||
|
"which ones are page urls of anitube.in.ua.[/]"]))
|
||||||
|
del config["URLS"]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_config(config_path:PosixPath, console:Console) -> dict:
|
||||||
|
"""
|
||||||
|
Read the configuration file and return dict as configuration.
|
||||||
|
The configuration file must be in the application folder.
|
||||||
|
"""
|
||||||
|
config = {}
|
||||||
|
try:
|
||||||
|
with open(config_path, "rb") as file:
|
||||||
|
config = tomli.load(file)
|
||||||
|
except FileNotFoundError:
|
||||||
|
console.print(f"[red][ERROR] Please, create configuration file.[/]")
|
||||||
|
console.print(f"[yellow][ERROR] The configuration file path: {config_path}.[/]")
|
||||||
|
except tomli.TOMLDecodeError:
|
||||||
|
console.print(f"[red][ERROR] Please, check configuration file for correctness.[/]")
|
||||||
|
Config.config_validation_error(config)
|
||||||
|
return config
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
##########################################################################
|
##########################################################################
|
||||||
# Copyright (C) 2022 Kostya Klochko <kostya_klochko@ukr.net> #
|
# Copyright (C) 2022-2023 Kostiantyn Klochko <kklochko@protonmail.com> #
|
||||||
# #
|
# #
|
||||||
# This file is part of Anitube Simple Notification. #
|
# This file is part of Anitube Simple Notification. #
|
||||||
# #
|
# #
|
||||||
@@ -29,22 +29,8 @@ class DataBase:
|
|||||||
def __init__(self, PATH: str = "user.db", TABLE: str = "animes"):
|
def __init__(self, PATH: str = "user.db", TABLE: str = "animes"):
|
||||||
"""Initialising the connection information."""
|
"""Initialising the connection information."""
|
||||||
self.PATH, self.TABLE = PATH, TABLE
|
self.PATH, self.TABLE = PATH, TABLE
|
||||||
self.database_is_exists()
|
|
||||||
self.create_table(self.TABLE)
|
self.create_table(self.TABLE)
|
||||||
|
|
||||||
def database_is_exists(self):
|
|
||||||
"""Creates DB file if not exists."""
|
|
||||||
try:
|
|
||||||
f = open(self.PATH, 'r')
|
|
||||||
f.close()
|
|
||||||
except FileNotFoundError:
|
|
||||||
f = open(self.PATH, 'w')
|
|
||||||
f.close()
|
|
||||||
except Exception as e:
|
|
||||||
print(f"{e=}")
|
|
||||||
finally:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def create_table(self, table):
|
def create_table(self, table):
|
||||||
"""Create a table in the DB."""
|
"""Create a table in the DB."""
|
||||||
connect = sqlite3.connect(self.PATH)
|
connect = sqlite3.connect(self.PATH)
|
||||||
|
|||||||
+47
-30
@@ -1,5 +1,5 @@
|
|||||||
##########################################################################
|
##########################################################################
|
||||||
# Copyright (C) 2022 Kostya Klochko <kostya_klochko@ukr.net> #
|
# Copyright (C) 2022-2023 Kostiantyn Klochko <kklochko@protonmail.com> #
|
||||||
# #
|
# #
|
||||||
# This file is part of Anitube Simple Notification. #
|
# This file is part of Anitube Simple Notification. #
|
||||||
# #
|
# #
|
||||||
@@ -17,64 +17,81 @@
|
|||||||
# along with Anitube Simple Notification. If not, see #
|
# along with Anitube Simple Notification. If not, see #
|
||||||
# <https://www.gnu.org/licenses/>. #
|
# <https://www.gnu.org/licenses/>. #
|
||||||
##########################################################################
|
##########################################################################
|
||||||
from db import DataBase
|
from .db import DataBase
|
||||||
from scraper import Scraper
|
from .scraper import Scraper
|
||||||
from notify import Notification
|
from .notify import Notification
|
||||||
|
from .config import Config
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.progress import track
|
||||||
import time
|
import time
|
||||||
|
import os
|
||||||
def get_urls(file_path):
|
import platformdirs
|
||||||
"""Read file that containes urls."""
|
|
||||||
urls = []
|
|
||||||
with open(file_path, 'r') as file:
|
|
||||||
for line in file:
|
|
||||||
if '\n' in line:
|
|
||||||
line = line.replace('\n', '')
|
|
||||||
urls.append(line)
|
|
||||||
return urls
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# Const sections.
|
# Const sections.
|
||||||
|
|
||||||
|
# Console initialising
|
||||||
|
console = Console()
|
||||||
|
|
||||||
|
APPNAME = "anitube-simple-notification"
|
||||||
|
APPAUTHOR = "KKlochko"
|
||||||
|
CONFIG_NAME = "config.toml"
|
||||||
|
BASE_DIR = os.path.dirname(__file__)
|
||||||
|
DATA_DIR = platformdirs.user_data_dir(APPNAME, APPAUTHOR)
|
||||||
|
|
||||||
|
DB_PATH = os.path.join(DATA_DIR, 'user.db')
|
||||||
|
POSTERS_PATH = os.path.join(DATA_DIR, 'posters')
|
||||||
|
|
||||||
|
CONFIG_PATH = platformdirs.user_config_path(APPNAME, APPAUTHOR, CONFIG_NAME)
|
||||||
|
|
||||||
|
# check for existing of dirs
|
||||||
|
if not os.path.exists(DATA_DIR):
|
||||||
|
os.makedirs(DATA_DIR)
|
||||||
|
|
||||||
|
if not os.path.exists(CONFIG_PATH):
|
||||||
|
os.makedirs(CONFIG_PATH)
|
||||||
|
|
||||||
|
config = Config.get_config(CONFIG_PATH, console)
|
||||||
|
|
||||||
# Here you can change testing headers to yours.
|
# Here you can change testing headers to yours.
|
||||||
HEADERS = {
|
HEADERS = {
|
||||||
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0'
|
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Default if empty.
|
||||||
MESSAGE = "New episode."
|
MESSAGE = "New episode."
|
||||||
URL_FILE = "urls"
|
WAITING_PERIOD = config.pop('WAITING_PERIOD', 60) # seconds
|
||||||
WAITING_PERIOD = 60 # seconds
|
POSTERS = config.pop('POSTERS', True) # for use poster as icons of notifications
|
||||||
POSTERS = True # For use poster as icons of notifications
|
urls = config.pop('URLS', [])
|
||||||
|
|
||||||
# Initialising objects
|
# Initialising objects
|
||||||
scr = Scraper(HEADERS)
|
scr = Scraper(HEADERS, POSTERS_PATH)
|
||||||
db = DataBase()
|
db = DataBase(DB_PATH)
|
||||||
|
|
||||||
# Reading the URL_FILE for making list
|
|
||||||
urls = get_urls(URL_FILE)
|
|
||||||
#print(f"{urls}")
|
|
||||||
|
|
||||||
# Checks for new urls in file and add as current state
|
# Checks for new urls in file and add as current state
|
||||||
# If one of page has updated then notifing.
|
# If one of page has updated then notifing.
|
||||||
# Repeating the checking with the waiting period.
|
# Repeating the checking with the waiting period.
|
||||||
while True:
|
while True:
|
||||||
print(f"[DOING] Checking for animes [0/{len(urls)}]")
|
console.print(f"[yellow][DOING][/] Checking for animes [0/{len(urls)}]")
|
||||||
count = 0
|
count = 0
|
||||||
for url in urls:
|
for url in urls:
|
||||||
data = scr.get_anime(url, POSTERS)
|
data = scr.get_anime(url, POSTERS)
|
||||||
if data == None:
|
if data == None:
|
||||||
print(f"[ERROR] A conections trouble is occured.")
|
console.print(f"[red][ERROR][/] A conections trouble is occured.")
|
||||||
continue
|
continue
|
||||||
url, title, status, poster_path = data
|
url, title, status, poster_path = data
|
||||||
print(f"[DOING] Checking for \"{title}\" [{count}/{len(urls)}]")
|
console.print(f"[yellow][DOING][/] Checking for \"{title}\" [{count}/{len(urls)}]")
|
||||||
r = db.add_anime_if(url, title, status, poster_path)
|
r = db.add_anime_if(url, title, status, poster_path)
|
||||||
if r == -1:
|
if r == -1:
|
||||||
n = Notification(title, MESSAGE, poster_path)
|
n = Notification(title, MESSAGE, poster_path)
|
||||||
n.send()
|
n.send()
|
||||||
print(f"[NOTIFICATION] \"{title}\"")
|
console.print(f"[blue bold][NOTIFICATION][/] \"{title}\"")
|
||||||
count+=1
|
count+=1
|
||||||
print(f"[DONE] Checking for \"{title}\" [{count}/{len(urls)}]")
|
console.print(f"[green][DONE][/] Checking for \"{title}\" [{count}/{len(urls)}]")
|
||||||
print(f"[WAITING] The next check is after {WAITING_PERIOD} seconds")
|
console.print(f"[yellow][WAITING][/] The next check is after {WAITING_PERIOD} seconds")
|
||||||
time.sleep(WAITING_PERIOD)
|
# Sleep while waiting
|
||||||
|
for n in track(range(WAITING_PERIOD), description="Waiting..."):
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
##########################################################################
|
##########################################################################
|
||||||
# Copyright (C) 2022 Kostya Klochko <kostya_klochko@ukr.net> #
|
# Copyright (C) 2022-2023 Kostiantyn Klochko <kklochko@protonmail.com> #
|
||||||
# #
|
# #
|
||||||
# This file is part of Anitube Simple Notification. #
|
# This file is part of Anitube Simple Notification. #
|
||||||
# #
|
# #
|
||||||
@@ -27,7 +27,7 @@ from notifypy import Notify
|
|||||||
class Notification:
|
class Notification:
|
||||||
"""The handler of notification."""
|
"""The handler of notification."""
|
||||||
def __init__(self, title, message, icon_path=""):
|
def __init__(self, title, message, icon_path=""):
|
||||||
"""Initialising the connection information."""
|
"""Initialising the notification information."""
|
||||||
self.title, self.message, self.icon_path = title, message, icon_path
|
self.title, self.message, self.icon_path = title, message, icon_path
|
||||||
|
|
||||||
def send(self):
|
def send(self):
|
||||||
|
|||||||
+9
-6
@@ -1,5 +1,5 @@
|
|||||||
##########################################################################
|
##########################################################################
|
||||||
# Copyright (C) 2022 Kostya Klochko <kostya_klochko@ukr.net> #
|
# Copyright (C) 2022-2023 Kostiantyn Klochko <kklochko@protonmail.com> #
|
||||||
# #
|
# #
|
||||||
# This file is part of Anitube Simple Notification. #
|
# This file is part of Anitube Simple Notification. #
|
||||||
# #
|
# #
|
||||||
@@ -24,6 +24,8 @@ This module has all for simplify work with scraping.
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.progress import track
|
||||||
import os
|
import os
|
||||||
|
|
||||||
class Scraper:
|
class Scraper:
|
||||||
@@ -63,9 +65,10 @@ class Scraper:
|
|||||||
poster_url = "https://anitube.in.ua" + soup.find('span', class_="story_post").find('img').get('src')
|
poster_url = "https://anitube.in.ua" + soup.find('span', class_="story_post").find('img').get('src')
|
||||||
poster_path = f"{self.POSTER_PATH}/{poster_url.split('/')[-1]}"
|
poster_path = f"{self.POSTER_PATH}/{poster_url.split('/')[-1]}"
|
||||||
if GETPOSTER and not self.file_exist(poster_path):
|
if GETPOSTER and not self.file_exist(poster_path):
|
||||||
print(f"[DONWLOADING] The poster for {title}")
|
console = Console()
|
||||||
img = requests.get(poster_url)
|
with console.status("[yellow]Downloading...[/]"):
|
||||||
with open(poster_path,'wb') as file:
|
img = requests.get(poster_url)
|
||||||
file.write(img.content)
|
with open(poster_path,'wb') as file:
|
||||||
print(f"[DONWLOADED] The poster for {title}")
|
file.write(img.content)
|
||||||
|
console.print(f"[green][DONWLOADED][/] The poster for \"{title}\"")
|
||||||
return [url, title, status, poster_path]
|
return [url, title, status, poster_path]
|
||||||
|
|||||||
Reference in New Issue
Block a user