from django.conf import settings from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType from django.core.cache import cache from django.db import models from django.utils import timezone from picklefield import PickledObjectField from telebot import TeleBot from yamlfield.fields import YAMLField from feeds.tasks import execute_feed class Feed(models.Model): owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) title = models.CharField(max_length=32) chat_id = models.CharField(max_length=33) check_interval = models.DurationField(help_text='in seconds') last_check = models.DateTimeField(null=True, blank=True) last_id = models.JSONField(null=True, blank=True) config_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) config_id = models.PositiveIntegerField() config = GenericForeignKey('config_type', 'config_id') @property def lock_key(self): return 'feed-{}-lock'.format(self.pk) @property def locked(self): return bool(cache.get(self.lock_key)) def run_check(self): if self.locked: return False if self.last_check and timezone.now() < self.last_check + self.check_interval: return False cache.set(self.lock_key, 1, timeout=60) execute_feed.apply_async(args=(self.pk,), shadow=str(self)) return True def __str__(self): return f'#{self.pk} {self.title}' class Meta: unique_together = ('config_type', 'config_id') class FeedModuleConfig(models.Model): _feeds = GenericRelation(Feed, content_type_field='config_type', object_id_field='config_id') MODULE_NAME = '' @property def feed(self): return self._feeds.get() @property def content_type(self): return ContentType.objects.get_for_model(self.__class__) def execute(self, bot: TeleBot, chat_id, last_id): raise NotImplementedError() class Meta: abstract = True