diff --git a/config/base.mplstyle b/config/mpl_styles/base.mplstyle similarity index 100% rename from config/base.mplstyle rename to config/mpl_styles/base.mplstyle diff --git a/config/default.expanded.mplstyle b/config/mpl_styles/default.expanded.mplstyle similarity index 100% rename from config/default.expanded.mplstyle rename to config/mpl_styles/default.expanded.mplstyle diff --git a/config/default.mplstyle b/config/mpl_styles/default.mplstyle similarity index 100% rename from config/default.mplstyle rename to config/mpl_styles/default.mplstyle diff --git a/config/small.expanded.mplstyle b/config/mpl_styles/small.expanded.mplstyle similarity index 100% rename from config/small.expanded.mplstyle rename to config/mpl_styles/small.expanded.mplstyle diff --git a/config/small.mplstyle b/config/mpl_styles/small.mplstyle similarity index 100% rename from config/small.mplstyle rename to config/mpl_styles/small.mplstyle diff --git a/config/volume.mplstyle b/config/mpl_styles/volume.mplstyle similarity index 100% rename from config/volume.mplstyle rename to config/mpl_styles/volume.mplstyle diff --git a/docs/development.md b/docs/development.md index cdd96343..91361146 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1,25 +1,19 @@ # Development - > Bitbot is somewhat cobbled together, but is fairly carefully commented and has been factored with ease of change in mind. ## βœ”οΈ Tests -> [python unittests](/tests) with the default test framework - - python3 -m unittest discover tests -v +[python unit tests](/tests) with the default test framework +`python3 -m unittest discover tests -v` ## βœ‰οΈ Env vars -> `BITBOT_TESTRUN` loads one chart and then exits - -> `BITBOT_SHOWIMAGE` [opens the image in vscode](/run.py) after loading the chart - -> `BITBOT_OUTPUT` may be set to `disk` to write to disk rather than the e-ink display - - export BITBOT_TESTRUN=true BITBOT_OUTPUT=disk BITBOT_SHOWIMAGE=true +`BITBOT_TESTRUN` loads one chart and then exits +`BITBOT_SHOWIMAGE` [opens the image in vscode](/run.py) after loading the chart +`BITBOT_OUTPUT` may be set to `disk` to write to disk rather than the e-ink display +`export BITBOT_TESTRUN=true BITBOT_OUTPUT=disk BITBOT_SHOWIMAGE=true` ## πŸ“» Easy WiFi config -> [`comitup`](https://github.com/davesteele/comitup) is used for the ***disk image***, it creates a **config hotspot** on the Pi if it **cant connect** to any wifi itself. - -> The config file is located at `/etc/comitup.conf` +[`comitup`](https://github.com/davesteele/comitup) is used for the ***disk image***, it creates a **config hotspot** on the Pi if it **cant connect** to any wifi itself. +The config file is located at `/etc/comitup.conf` ```sh # show comitup info sudo comitup -i @@ -28,11 +22,9 @@ sudo comitup-cli ``` ## 🌳Logging -> BitBot will log to `syslog`, `StdOut` and a rolling `debug.log` file, configured in [πŸ“logging.ini](/logging.ini) - -> Log level is **defaulted to `INFO`**, but there is some ***limited debug level logging*** if you wish to get more info. - -> Cron jobs were configured to output to syslog. 😞 +BitBot will log to the `config web-ui` `syslog`, `StdOut` and a rolling `debug.log` file, configured in [πŸ“logging.ini](/logging.ini) +Log level is **defaulted to `INFO`**, but there is some ***limited debug level logging*** if you wish to get more info. +Cron jobs were configured to output to syslog. 😞 ```sh # roling file log tail ~/bitbot/debug.log @@ -41,23 +33,22 @@ tail -f /var/log/syslog | grep 'Bitbot:' ``` ## 🎁 Packages +UML diagram of broad [package interactions](http://www.plantuml.com/plantuml/svg/3Oon3KCX30NxFqMo0EvJ_LN0M7mhO11-LjOFrUckkDkHDsBqwwt6FQh4xgy7MFuXslcNckA94YwRfq4CYUUWEgseDIgACa4Zgvt6JcT5A_CtD_6qZbstM3ty0m00) + - [Pimoroni](pimoroni.com) [`inky`](https://github.com/pimoroni/inky) does the **e-ink display**, - [`CCXT`](https://github.com/ccxt/ccxt) talks to **crypto exchanges** - [`MPL-Finance`](https://github.com/matplotlib/mpl-finance) **draws the graphs** (and could do with updating to [`mplfinance`](https://github.com/matplotlib/mplfinance)) - [`Pillow`](https://github.com/python-pillow/Pillow) draws **drawing overlay** text onto the graph -![Package Interactions](http://www.plantuml.com/plantuml/svg/3Oon3KCX30NxFqMo0EvJ_LN0M7mhO11-LjOFrUckkDkHDsBqwwt6FQh4xgy7MFuXslcNckA94YwRfq4CYUUWEgseDIgACa4Zgvt6JcT5A_CtD_6qZbstM3ty0m00) - ## 🐳 Docker -> **Github actions** builds and tests and publishes a **container image** on each commit to `main` and `release` -### 🐳 Build -> building on `x86` is way faster than on the Pi +**Github actions** builds and tests and publishes a **container image** on each commit to `main` and `release` + +🐳 Build on `x86` is way faster than on the Pi. ```sh # remove the `--platform` args if building on a pi docker buildx build --platform linux/arm/v6 . -t bitbot -f scripts/docker/dockerfile --progress string ``` -### 🐳 Run -> **Priviledged access** is needed for `GPIO`, this looks to be fixable thru bind mounts +🐳 Run **Priviledged access** is needed for `GPIO`, this looks to be fixable thru bind mounts. ```sh docker run --privileged --platform linux/arm/v6 bitbot ``` \ No newline at end of file diff --git a/docs/device_setup.md b/docs/device_setup.md index f2107413..84a27654 100644 --- a/docs/device_setup.md +++ b/docs/device_setup.md @@ -24,7 +24,7 @@ - A list of **supported crypto-exchanges** can be found [here](https://github.com/ccxt/ccxt/wiki/Exchange-Markets) - Please see your selected exchange for the ***instruments that it supports*** -### Bitbot uses [Style Files](../config/base.mplstyle) to control the chart layout. +### Bitbot uses [Style Files](../config/mpl_styles/base.mplstyle) to control the chart layout. - If you're feeling experimental.. you can edit these! Examples of the ***styling*** options can be [found here](https://matplotlib.org/stable/tutorials/introductory/customizing.html#the-default-matplotlibrc-file) ### Inky Impression **Button** support diff --git a/docs/docker_installation.md b/docs/docker_installation.md deleted file mode 100644 index 761a5bef..00000000 --- a/docs/docker_installation.md +++ /dev/null @@ -1,36 +0,0 @@ -# πŸ‹ How to install Docker - -1. ### Update the host package manager -```sh -sudo apt update -y -``` -2. ### Install docker -```sh -curl -fsSL https://get.docker.com -o get-docker.sh -sudo sh get-docker.sh -``` -3. ### Setup user -```sh -sudo usermod -aG docker pi -``` -4. ### docker compose -```sh -sudo curl -fL 'https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-linux-armv6' -o /usr/local/bin/docker-compose -sudo chmod +x /usr/local/bin/docker-compose -``` -5. ### Reboot -```sh -sudo shutdown -r now -``` -6. ### Run bitbot image - -- `main` - ```shell - docker run --restart unless-stopped --privileged ghcr.io/donbing/bitbot:main - docker run -it --privileged ghcr.io/donbing/bitbot:main - docker-compose -f scripts/docker/docker-compose.yml up - ``` -- `release` (stable) - ```shell - docker run --restart unless-stopped --privileged ghcr.io/donbing/bitbot:release - ``` \ No newline at end of file diff --git a/docs/notes.md b/docs/notes.md index 19e72e70..02af466f 100644 --- a/docs/notes.md +++ b/docs/notes.md @@ -26,10 +26,10 @@ todo: - moving averages - indicators - -> Build arm6 on x86 +# Docker +Build arm6 on x86 ```bash - docker run -e QEMU_CPU=arm1176 --privileged --rm -it --platform linux/arm/v6 balenalib/raspberry-pi:buster bash +docker run -e QEMU_CPU=arm1176 --privileged --rm -it --platform linux/arm/v6 balenalib/raspberry-pi:buster bash # build container atrm6 docker buildx build --platform linux/arm/v6 . -t bitbot --progress string # run it, have to specify which chip QEMU should emulate @@ -37,22 +37,27 @@ docker run -e QEMU_CPU=arm1176 --privileged --rm -t --platform linux/arm/v6 navi docker buildx build --platform linux/arm/v6 . -t bitbot -f scripts/docker/dockerfile --progress string docker run -e QEMU_CPU=arm1176 --privileged --rm -it --platform linux/arm/v6 bitbot +``` +# Hackery +```bash # remove all containers docker container rm $(docker container ls -q -a) #' which cpus to use for the build # --cpuset-cpus=0-3' -# wifi-connect docker pull balenablocks/wifi-connect:rpi -docker run --network=host -v /run/dbus/:/run/dbus/ balenablocks/wifi-connect:rpi # error: failed to solve: failed to solve with frontend dockerfile.v0: failed to create LLB definition: rpc error: code = Unknown desc = error getting credentials - err: exit status 255, out: `` = In ~/.docker/config.json `change credsStore to credStore` # error exec "--env" "executable file not found in $PATH: unknown" = badly ordered docker args, envs must come before image name +``` +# Testing +```bash # test run docker run --rm --env BITBOT_TESTRUN=true --env BITBOT_OUTPUT=disk --env BITBOT_SHOWIMAGE=false bb + # run tests docker run --rm \ --name bitbot_tests \ @@ -62,17 +67,24 @@ bb \ python3 -m unittest discover ``` -> get linux os version +# PiOS +Get linux os version ```sh cat /etc/os-release ``` -> enable vnc raspiconfig +Enable vnc raspiconfig ```sh sudo raspi-config nonint do_vnc 0 ``` -> setup my git +Check cpu arch +```sh +dpkg --print-architecture +``` + +# Git +Setup my git ```sh # setup user git config --global user.email ccbing@gmail.com @@ -87,38 +99,9 @@ git config --global --unset user.password git config --global alias.ci commit git config --global alias.st status ``` -> check cpu arch -```sh -dpkg --print-architecture -``` - - -## fonts -> place in `~/.fonts` or `/usr/local/share/fonts` for system wide access - mkdir ~/.fonts && cp ~/bitbot/src/resources/04B_03__.TTF ~/.fonts/04B_03__.TTF - -> manually rebuild the font cache with `fc-cache -f -v` - -> list fonts with `fc-list` - - - -# balena -``` -# install gbalena cli -wget https://github.com/balena-io/balena-cli/releases/download/v13.3.0/balena-cli-v13.3.0-linux-x64-standalone.zip -unzip balena-cli-v13.3.0-linux-x64-standalone.zip -# balena cli -balena login -balena push gh_donbing/teste -# git -# add pud key to balena -balena key add Main ~/.ssh/id_rsa.pub -# list keys -balena keys -# push to balena -git remote add balena gh_donbing@git.balena-cloud.com:gh_donbing/teste.git -# push our main branch to balena master branch -git push balena main:master -``` +# Fonts +- place in `~/.fonts` or `/usr/local/share/fonts` for system wide access +- `mkdir ~/.fonts && cp ~/bitbot/src/resources/04B_03__.TTF ~/.fonts/04B_03__.TTF` +- manually rebuild the font cache with `fc-cache -f -v` +- list fonts with `fc-list` diff --git a/readme.md b/readme.md index 35557f95..2a3b1fca 100644 --- a/readme.md +++ b/readme.md @@ -35,5 +35,4 @@ - [βš™οΈ Device **Setup**](docs/device_setup.md) - [πŸ’Ύ **Config** Options](docs/config_options.md) - [πŸ“’ Dev **Notes**](docs/development.md) - - [πŸ‹ **Docker** Setup](docs/docker_installation.md) - - [πŸ“ˆ Current charting examples](/tests/images/) + - [πŸ“ˆ Chart examples](/tests/images/) diff --git a/run.py b/run.py index f2008ae6..3d63b225 100644 --- a/run.py +++ b/run.py @@ -36,11 +36,13 @@ def refresh_display(sc, reason): if config.photo_mode_enabled(): if reason != "scheduled": app.display_photo() - else: - app.display_chart() + elif app.display_chart(): # πŸͺ³ show image in vscode for debug if config.shoud_show_image_in_vscode(): os.system("code last_display.png") + elif app.youtube_subs_enabled(): + app.display_youtube_subs() + # βŒ› dont reschedule if testing if not config.is_test_run(): diff --git a/src/bitbot.py b/src/bitbot.py index 23e5c158..4265f00e 100644 --- a/src/bitbot.py +++ b/src/bitbot.py @@ -1,4 +1,4 @@ -from PIL import Image, ImageDraw, ImageFont +from PIL import Image, ImageDraw from os.path import exists import io from src.exchanges import crypto_exchanges, stock_exchanges @@ -7,6 +7,7 @@ from src.drawing.chart_overlay import ChartOverlay from src.display.picker import picker as display_picker from src.configuration.network_utils import wait_for_internet_connection +from src.youtube_stats.subscriber_counter import YouTubeSubscriberCount class Cartographer(): @@ -68,5 +69,10 @@ def display_photo(self): if(exists(image_path)): self.display.show(Image.open(image_path)) + @info_log + def display_youtube_subs(self): + subscriber_display = YouTubeSubscriberCount(self.display.size(), self.display.title_font, self.config) + subscriber_display.play() + def __repr__(self): return f'' diff --git a/src/configuration/bitbot_config.py b/src/configuration/bitbot_config.py index bb1ca71e..cb0c2bb6 100644 --- a/src/configuration/bitbot_config.py +++ b/src/configuration/bitbot_config.py @@ -134,13 +134,13 @@ def set_display(self, formData): self.save() # πŸ–ΌοΈ picture frame mode + def photo_mode_enabled(self): + return self.config['picture_frame_mode']["enabled"] == 'true' + def toggle_photo_mode(self, enabled_state, cycle_state): self.config['picture_frame_mode']["enabled"] = enabled_state self.config['picture_frame_mode']["cycle_pictures"] = cycle_state - def photo_mode_enabled(self): - return self.config['picture_frame_mode']["enabled"] == 'true' - def cycle_pictures_enabled(self): return self.config['picture_frame_mode']["cycle"] == 'true' @@ -188,3 +188,13 @@ def intro_background(self): self.config_files.resource_folder, self.config['first_run']['intro_background_image'] ) + + # πŸ“Ί youtube setup + def youtube_subs_enabled(self): + return self.config['youtube_subs']["enabled"] == 'true' + + def youtube_channelid(): + return "UCAotflAHrgfuhK9Rw-C_-Ug" + + def youtube_key(): + return "AIzaSyCFJ6-vHN9KgOE3a6mjdqBcG-pYlwcRGj4" \ No newline at end of file diff --git a/src/configuration/bitbot_files.py b/src/configuration/bitbot_files.py index 5dd048ee..d87671f4 100644 --- a/src/configuration/bitbot_files.py +++ b/src/configuration/bitbot_files.py @@ -23,13 +23,20 @@ def __init__(self, base_path): self.config_ini = self.existing_file_path('config.ini') self.logging_ini = self.existing_file_path('logging.ini') - self.base_style = self.existing_file_path('base.mplstyle') - self.default_style = self.existing_file_path('default.mplstyle') - self.volume_style = self.existing_file_path('volume.mplstyle') - self.small_screen_style = self.existing_file_path('small.mplstyle') - self.expanded_style = self.existing_file_path('default.expanded.mplstyle') - self.small_expanded_style = self.existing_file_path('small.expanded.mplstyle') - + self.base_style = self.load_mpl_style('base.mplstyle') + self.default_style = self.load_mpl_style('default.mplstyle') + self.volume_style = self.load_mpl_style('volume.mplstyle') + self.small_screen_style = self.load_mpl_style('small.mplstyle') + self.expanded_style = self.load_mpl_style('default.expanded.mplstyle') + self.small_expanded_style = self.load_mpl_style('small.expanded.mplstyle') + + def load_mpl_style(self, file_name): + file_path = pjoin(self.config_folder, 'mpl_styles', file_name) + if not exists(file_path): + self.file_not_found(file_path) + self.all_files[file_name] = file_path + return file_path + def existing_file_path(self, file_name): file_path = pjoin(self.config_folder, file_name) if not exists(file_path): diff --git a/src/drawing/legacy_mpf_plotted_chart.py b/src/drawing/legacy_mpf_plotted_chart.py deleted file mode 100644 index abaecbc0..00000000 --- a/src/drawing/legacy_mpf_plotted_chart.py +++ /dev/null @@ -1,97 +0,0 @@ -import matplotlib -import tzlocal -import matplotlib.pyplot as plt -import matplotlib.dates as mdates -from mplfinance.original_flavor import candlestick_ohlc, volume_overlay -from src.drawing import price_humaniser - -matplotlib.use('Agg') -local_tz = tzlocal.get_localzone() - -price_formatter = matplotlib.ticker.FuncFormatter( - price_humaniser.format_scale_price -) - - -class PlottedChart: - layouts = { - '3mo': (20, mdates.YearLocator(), mdates.YearLocator(1), mdates.DateFormatter('%Y'), local_tz), - '1mo': (0.01, mdates.MonthLocator(), mdates.YearLocator(1), mdates.DateFormatter('%Y'), local_tz), - '1d': (0.01, mdates.DayLocator(bymonthday=range(1, 31, 7)), mdates.MonthLocator(), mdates.DateFormatter('%b'), local_tz), - '1h': (0.005, mdates.HourLocator(byhour=range(0, 23, 4)), mdates.DayLocator(), mdates.DateFormatter('%a %d %b', local_tz)), - "5m": (0.0005, mdates.MinuteLocator(byminute=[0, 30]), mdates.HourLocator(interval=1), mdates.DateFormatter('%-I.%p', local_tz)), - } - - def __init__(self, config, display, files, chart_data): - self.candle_width = chart_data.candle_width - # πŸ–¨οΈ create MPL plot - self.fig, ax = self.create_chart_figure(config, display, files) - # πŸ“ find suiteable layout for timeframe - layout = self.layouts[self.candle_width] - # βž– locate/format x axis ticks for chosen layout - ax[0].xaxis.set_minor_locator(layout[1]) - ax[0].xaxis.set_minor_formatter(plt.NullFormatter()) - ax[0].xaxis.set_major_locator(layout[2]) - ax[0].xaxis.set_major_formatter(layout[3]) - # πŸ’²currency amount uses custom formatting - ax[0].yaxis.set_major_formatter(price_formatter) - - self.plot_chart(config, layout, ax, chart_data.candle_data) - - def plot_chart(self, config, layout, ax, candle_data): - # βœ’οΈ draw candles to MPL plot - candlestick_ohlc(ax[0], candle_data, colorup='green', colordown='red', width=layout[0]) - # βœ’οΈ draw volumes to MPL plot - if config.show_volume(): - ax[1].yaxis.set_major_formatter(price_formatter) - _, opens, _, _, closes, volumes = list(zip(*candle_data)) - volume_overlay(ax[1], opens, closes, volumes, colorup='white', colordown='red', width=1) - self.fig.subplots_adjust(bottom=0.01) - - # πŸ“‘ styles overide each other left to right? - def get_default_styles(self, config, display, files): - small_display = self.is_small_display(display) - - if small_display: - yield files.small_screen_style - yield files.default_style - - if config.expand_chart(): - yield files.expanded_style - if small_display: - yield files.small_expanded_style - - def is_small_display(self, display): - small_display = display.size()[0] < 300 - return small_display - - def create_chart_figure(self, config, display, files): - # πŸ“ apply global base style - plt.style.use(files.base_style) - num_plots = 2 if config.show_volume() else 1 - heights = [4, 1] if config.show_volume() else [1] - plt.tight_layout() - # πŸ“ select mpl style - stlyes = list(self.get_default_styles(config, display, files)) - # πŸ“ scope styles to just this plot - with plt.style.context(stlyes): - display_width, display_height = display.size() - fig = plt.figure(figsize=(display_width / 100, display_height / 100)) - gs = fig.add_gridspec(num_plots, hspace=0, height_ratios=heights) - ax1 = fig.add_subplot(gs[0], zorder=1) - ax2 = None - - # πŸ“ align price tick labels for expanded chart - if(config.expand_chart()): - ax1.set_yticklabels(ax1.get_yticklabels(), ha='left') - - if config.show_volume(): - with plt.style.context(files.volume_style): - ax2 = fig.add_subplot(gs[1], zorder=0) - - return (fig, (ax1, ax2)) - - def write_to_stream(self, stream): - self.fig.savefig(stream, dpi=self.fig.dpi, pad_inches=0) - stream.seek(0) - plt.close(self.fig) diff --git a/src/youtube_stats/subscriber_counter.py b/src/youtube_stats/subscriber_counter.py new file mode 100644 index 00000000..b7369cc5 --- /dev/null +++ b/src/youtube_stats/subscriber_counter.py @@ -0,0 +1,30 @@ +from PIL import Image, ImageDraw +from ..drawing.image_utils.CenteredText import centered_text +from ..configuration.network_utils import wait_for_internet_connection +import json +import requests + +transparent = (255, 0, 0, 0) + +class YouTubeSubscriberCount: + def __init__(self, size, font, config): + self.config = config + self.display_size = size + self.font = font + self.centre = tuple(dim / 2 for dim in self.display_size.size) + + def play(self): + channel_id=self.config.youtube_channelid() + your_key=self.config.youtube_key() + url = f"https://www.googleapis.com/youtube/v3/channels?part=statistics&id={channel_id}&key={your_key}" + http_response = requests.get(url) + response_json = json.loads(http_response.text) + subscriber_count = response_json['items'][0]['statistics']['subscriberCount'] + text_to_draw = f"{subscriber_count} Subscribers" + img = Image.new("RGBA", self.display_size.size, transparent) + draw = ImageDraw.Draw(img) + centered_text(draw, text_to_draw, self.font, self.display_size, 'centre') + return img + + def no_op(self): + pass diff --git a/tests/images/test_264x176_APPLE_1mo_defaults.fail.png b/tests/images/test_264x176_APPLE_1mo_defaults.fail.png deleted file mode 100644 index 110a6b49..00000000 Binary files a/tests/images/test_264x176_APPLE_1mo_defaults.fail.png and /dev/null differ diff --git a/tests/images/test_264x176_APPLE_3mo_defaults.fail.png b/tests/images/test_264x176_APPLE_3mo_defaults.fail.png deleted file mode 100644 index 97052bc0..00000000 Binary files a/tests/images/test_264x176_APPLE_3mo_defaults.fail.png and /dev/null differ diff --git a/tests/images/test_264x176_AUDCAD_3mo_defaults_with_entry.fail.png b/tests/images/test_264x176_AUDCAD_3mo_defaults_with_entry.fail.png deleted file mode 100644 index 6f71e5fc..00000000 Binary files a/tests/images/test_264x176_AUDCAD_3mo_defaults_with_entry.fail.png and /dev/null differ diff --git a/tests/images/test_264x176_MSFT_3mo_defaults_with_entry.png b/tests/images/test_264x176_MSFT_3mo_defaults_with_entry.png new file mode 100644 index 00000000..b912725a Binary files /dev/null and b/tests/images/test_264x176_MSFT_3mo_defaults_with_entry.png differ diff --git a/tests/images/test_264x176_TSLA_3mo_defaults.png b/tests/images/test_264x176_TSLA_3mo_defaults.png new file mode 100644 index 00000000..f40b2d83 Binary files /dev/null and b/tests/images/test_264x176_TSLA_3mo_defaults.png differ diff --git a/tests/images/test_264x176_bitmex_BTC_1d_defaults.fail.png b/tests/images/test_264x176_bitmex_BTC_1d_defaults.fail.png deleted file mode 100644 index 93de4639..00000000 Binary files a/tests/images/test_264x176_bitmex_BTC_1d_defaults.fail.png and /dev/null differ diff --git a/tests/images/test_264x176_bitmex_BTC_1h_100K.fail.png b/tests/images/test_264x176_bitmex_BTC_1h_100K.fail.png deleted file mode 100644 index 15fc525f..00000000 Binary files a/tests/images/test_264x176_bitmex_BTC_1h_100K.fail.png and /dev/null differ diff --git a/tests/images/test_264x176_bitmex_BTC_1h_defaults.fail.png b/tests/images/test_264x176_bitmex_BTC_1h_defaults.fail.png deleted file mode 100644 index 66c3c878..00000000 Binary files a/tests/images/test_264x176_bitmex_BTC_1h_defaults.fail.png and /dev/null differ diff --git a/tests/images/test_264x176_bitmex_BTC_5m_defaults.fail.png b/tests/images/test_264x176_bitmex_BTC_5m_defaults.fail.png deleted file mode 100644 index e4a85547..00000000 Binary files a/tests/images/test_264x176_bitmex_BTC_5m_defaults.fail.png and /dev/null differ diff --git a/tests/images/test_264x176_bitmex_ETH_1d_defaults.fail.png b/tests/images/test_264x176_bitmex_ETH_1d_defaults.fail.png deleted file mode 100644 index 140fa773..00000000 Binary files a/tests/images/test_264x176_bitmex_ETH_1d_defaults.fail.png and /dev/null differ diff --git a/tests/images/test_264x176_bitmex_ETH_1h_defaults.fail.png b/tests/images/test_264x176_bitmex_ETH_1h_defaults.fail.png deleted file mode 100644 index eb2b2672..00000000 Binary files a/tests/images/test_264x176_bitmex_ETH_1h_defaults.fail.png and /dev/null differ diff --git a/tests/images/test_264x176_bitmex_ETH_5m_defaults.fail.png b/tests/images/test_264x176_bitmex_ETH_5m_defaults.fail.png deleted file mode 100644 index 3bd4989c..00000000 Binary files a/tests/images/test_264x176_bitmex_ETH_5m_defaults.fail.png and /dev/null differ diff --git a/tests/images/test_400x300_MSFT_3mo_defaults_with_entry.png b/tests/images/test_400x300_MSFT_3mo_defaults_with_entry.png new file mode 100644 index 00000000..8a449144 Binary files /dev/null and b/tests/images/test_400x300_MSFT_3mo_defaults_with_entry.png differ diff --git a/tests/images/test_400x300_TSLA_3mo_defaults.png b/tests/images/test_400x300_TSLA_3mo_defaults.png new file mode 100644 index 00000000..7af27169 Binary files /dev/null and b/tests/images/test_400x300_TSLA_3mo_defaults.png differ diff --git a/tests/images/test_640x448_MSFT_3mo_defaults_with_entry.png b/tests/images/test_640x448_MSFT_3mo_defaults_with_entry.png new file mode 100644 index 00000000..cd552257 Binary files /dev/null and b/tests/images/test_640x448_MSFT_3mo_defaults_with_entry.png differ diff --git a/tests/images/test_640x448_TSLA_3mo_defaults.png b/tests/images/test_640x448_TSLA_3mo_defaults.png new file mode 100644 index 00000000..c557b716 Binary files /dev/null and b/tests/images/test_640x448_TSLA_3mo_defaults.png differ diff --git a/tests/images/title_block2.png b/tests/images/title_block2.png new file mode 100644 index 00000000..79975025 Binary files /dev/null and b/tests/images/title_block2.png differ diff --git a/tests/images/youtube_subs_count.png b/tests/images/youtube_subs_count.png new file mode 100644 index 00000000..54052d31 Binary files /dev/null and b/tests/images/youtube_subs_count.png differ diff --git a/tests/test_chart_rendering.py b/tests/test_chart_rendering.py index 52bd8ae7..93377a2c 100644 --- a/tests/test_chart_rendering.py +++ b/tests/test_chart_rendering.py @@ -59,16 +59,19 @@ class disk_output_renderers: 'currency': {'stock_symbol': 'AAPL'}, 'display': {'candle_width': '1mo'}, }, - "APPLE_3mo_defaults": { - 'currency': {'stock_symbol': 'TSLA'}, + "TSLA_3mo_defaults": { + 'currency': { + 'chart_since': '2016-04-22T00:00:00Z', + 'stock_symbol': 'TSLA' + }, 'display': {'candle_width': '3mo'}, }, - "TSLA_3mo_defaults_with_entry": { + "MSFT_3mo_defaults_with_entry": { 'display': {'candle_width': '3mo'}, 'currency': { - 'stock_symbol': 'TSLA', + 'stock_symbol': 'MSFT', 'entry_price': '167', - #'chart_since': '2020-04-22T00:00:00Z', # yfinance limits to gathering 7 days of low-timeframe from the last 60 days + 'chart_since': '2016-04-22T00:00:00Z', # yfinance limits to gathering 7 days of low-timeframe from the last 60 days 'holdings': '10', }, }, @@ -192,7 +195,7 @@ def test(self): # os.system("code '" + file_name + "'") # if changes[1] is not None: # os.system("code '" + changes[1] + "'") - assert False, f"Image diff check: '{changes[1]}'" + assert False, f"Image diff check: '{changes}'" return test @@ -217,11 +220,11 @@ class LargeChartRenderingTests(unittest.TestCase, output=disk_output_renderers.d __metaclass__ = TestRenderingMeta -# @unittest.skip("needs a waveshare display") -# class Wave27bChartRenderingTests(unittest.TestCase, output=screen_output_renderers.wave27b, metaclass=TestRenderingMeta): -# __metaclass__ = TestRenderingMeta +@unittest.skip("needs a waveshare display") +class Wave27bChartRenderingTests(unittest.TestCase, output=screen_output_renderers.wave27b, metaclass=TestRenderingMeta): + __metaclass__ = TestRenderingMeta -# @unittest.skip("needs an inky display") -# class InkyChartRenderingTests(unittest.TestCase, output=screen_output_renderers.inky, metaclass=TestRenderingMeta): -# __metaclass__ = TestRenderingMeta +@unittest.skip("needs an inky display") +class InkyChartRenderingTests(unittest.TestCase, output=screen_output_renderers.inky, metaclass=TestRenderingMeta): + __metaclass__ = TestRenderingMeta diff --git a/tests/test_stock_exchange.py b/tests/test_stock_exchange.py index 48c3378e..c996b71b 100644 --- a/tests/test_stock_exchange.py +++ b/tests/test_stock_exchange.py @@ -11,7 +11,7 @@ test_params = ['1mo', '1h', '1wk', 'random'] curdir = pathlib.Path(__file__).parent.resolve() -files = use_config_dir(os.path.join(curdir, "../")) +files = use_config_dir(os.path.join(curdir, "..")) config_ini = load_config_ini(files) # πŸͺ³ ''1h',' <- fails on weekends due to short chart duration diff --git a/tests/test_youtube_subs.py b/tests/test_youtube_subs.py new file mode 100644 index 00000000..6def3563 --- /dev/null +++ b/tests/test_youtube_subs.py @@ -0,0 +1,24 @@ +import unittest +from src.display import title_font +from src.youtube_stats import subscriber_counter +from os.path import join as pjoin +import pathlib +from src.configuration.bitbot_files import use_config_dir +from src.configuration.bitbot_config import load_config_ini + +curdir = pathlib.Path(__file__).parent.resolve() +files = use_config_dir(pjoin(curdir, "../")) +config = load_config_ini(files) + +class DisplaySize(): + def __init__(self, size): + self.size = size + +@unittest.skip("needs youtube api key") +class YouTubeSubsTests(unittest.TestCase): + display_size = DisplaySize((400, 300)) + + def test_showing_youtube_subscriber_count(self): + aubscriber_count_display = subscriber_counter.YouTubeSubscriberCount(self.display_size, title_font, config) + image = aubscriber_count_display.play() + image.save(f'tests/images/youtube_subs_count.png')