next_slide.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #!/usr/bin/env python3
  2. """
  3. Copyright © 2023 Noah Vogt <noah@noahvogt.com>
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. """
  15. from datetime import date
  16. from re import match
  17. from os import path
  18. from pyautogui import hotkey
  19. from utils import log, error_msg
  20. import config as const
  21. def calculate_date() -> str:
  22. return date.strftime(date.today(), "%Y-%m-%d")
  23. def get_cachefile_content() -> list:
  24. try:
  25. with open(
  26. const.NEXTSONG_CACHE_FILE, mode="r", encoding="utf8"
  27. ) as cachefile_reader:
  28. cachefile_content = cachefile_reader.readlines()
  29. except (FileNotFoundError, PermissionError, IOError) as error:
  30. error_msg(
  31. "Failed to access cachefile in '{}'. Reason: {}".format(
  32. const.NEXTSONG_CACHE_FILE, error
  33. )
  34. )
  35. return cachefile_content
  36. def cycle_to_next_slide() -> None:
  37. cachefile_content = get_cachefile_content()
  38. if (
  39. not (
  40. len(cachefile_content) == 2
  41. and match(r"[0-9]{4}-[0-9]{2}-[0-9]{2}$", cachefile_content[0])
  42. and match(r"^[0-9]*$", cachefile_content[1])
  43. )
  44. or cachefile_content[0].strip() != calculate_date()
  45. ):
  46. switch_to_slide(1)
  47. else:
  48. switch_to_slide(int(cachefile_content[1]) + 1)
  49. def switch_to_slide(slide: int) -> None:
  50. if slide > const.OBS_MIN_SUBDIRS:
  51. slide = 1
  52. log("sending hotkey Ctr + Shift + F{}".format(slide))
  53. hotkey("ctrl", "shift", "f{}".format(slide))
  54. create_cachfile_for_slide(slide)
  55. def create_cachfile_for_slide(slide) -> None:
  56. log("writing slide {} cachefile...".format(slide))
  57. try:
  58. with open(
  59. const.NEXTSONG_CACHE_FILE, mode="w", encoding="utf8"
  60. ) as file_writer:
  61. file_writer.write(calculate_date() + "\n")
  62. file_writer.write(str(slide) + "\n")
  63. except (FileNotFoundError, PermissionError, IOError) as error:
  64. error_msg(
  65. "Failed to write to cachefile '{}'. Reason: {}".format(
  66. const.NEXTSONG_CACHE_FILE, error
  67. )
  68. )
  69. def validate_config() -> None:
  70. if const.NEXTSONG_CACHE_FILE == "":
  71. error_msg("needed config entry 'NEXTSONG_CACHE_FILE' is empty")
  72. if const.OBS_MIN_SUBDIRS == "":
  73. error_msg("needed config entry 'OBS_MIN_SUBDIRS' is empty")
  74. log("configuration initialised")
  75. def make_sure_cachefile_exists() -> None:
  76. if not path.isfile(const.NEXTSONG_CACHE_FILE):
  77. try:
  78. with open(
  79. const.NEXTSONG_CACHE_FILE, mode="w+", encoding="utf8"
  80. ) as file_creator:
  81. file_creator.write("")
  82. except (FileNotFoundError, PermissionError, IOError) as error:
  83. error_msg(
  84. "Failed to create cachefile in '{}'. Reason: {}".format(
  85. const.NEXTSONG_CACHE_FILE, error
  86. )
  87. )
  88. def main() -> None:
  89. validate_config()
  90. make_sure_cachefile_exists()
  91. cycle_to_next_slide()
  92. if __name__ == "__main__":
  93. main()