- Clips should only be accepted under certain conditions layed out in the database.
--- Clip for channels
--- Clip needs to be created within a timeframe
--- Clip needs to be created by user adding the clip
+-- Allow admin site to add username instead of broadcaster id in ResetData
- Implement Clip categories
- Display clip info more clearly
-- Who uploaded the clip
-- Clip comments
+
+- Refresh tokens
from django.contrib import admin
# Register your models here.
-from .models import Clip, ResetData
+from .models import Clip, ResetData, AllowedChannel
+
+
+class AllowedChannelInline(admin.TabularInline):
+ model = AllowedChannel
+
+
+class ResetDataAdmin(admin.ModelAdmin):
+ inlines = [
+ AllowedChannelInline,
+ ]
+
admin.site.register(Clip)
-admin.site.register(ResetData)
+admin.site.register(ResetData, ResetDataAdmin)
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
-class TooManyClips(Exception):
+
+
+class TooManyClipsError(Exception):
+ pass
+
+
+class TooLateError(Exception):
+ pass
+
+
+class ChannelNotAllowedError(Exception):
+ pass
+
+
+class UserNotCreatedClipError(Exception):
+ pass
+
+
+class ClipTooOldError(Exception):
pass
--- /dev/null
+# Generated by Django 4.1.5 on 2023-01-23 11:51
+
+import datetime
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("manager", "0012_resetdata_ranks"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="resetdata",
+ name="clip_limit_to_channels",
+ field=models.JSONField(null=True),
+ ),
+ migrations.AddField(
+ model_name="resetdata",
+ name="clip_newer_than",
+ field=models.DateTimeField(default=datetime.datetime(1970, 1, 1, 0, 0, 1)),
+ ),
+ migrations.AddField(
+ model_name="resetdata",
+ name="user_created_clip",
+ field=models.BooleanField(default=True),
+ ),
+ ]
--- /dev/null
+# Generated by Django 4.1.5 on 2023-01-23 12:03
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("manager", "0013_resetdata_clip_limit_to_channels_and_more"),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name="AllowedChannel",
+ fields=[
+ (
+ "id",
+ models.BigAutoField(
+ auto_created=True,
+ primary_key=True,
+ serialize=False,
+ verbose_name="ID",
+ ),
+ ),
+ ("broadcaster_id", models.CharField(max_length=100)),
+ (
+ "reset_data",
+ models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ to="manager.resetdata",
+ ),
+ ),
+ ],
+ ),
+ ]
--- /dev/null
+# Generated by Django 4.1.5 on 2023-01-23 12:14
+
+import datetime
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("manager", "0014_allowedchannel"),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name="resetdata",
+ name="clip_limit_to_channels",
+ ),
+ migrations.AddField(
+ model_name="resetdata",
+ name="end_date_time",
+ field=models.DateTimeField(default=datetime.datetime(2038, 1, 19, 3, 14)),
+ ),
+ ]
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
+from datetime import datetime
from django.db import models
from django.contrib.auth.models import User
class ResetData(models.Model):
date_time = models.DateTimeField()
+ end_date_time = models.DateTimeField(default=datetime.utcfromtimestamp(2147483640))
max_clips = models.IntegerField(default=2)
ranks = models.IntegerField(default=5)
+ user_created_clip = models.BooleanField(default=True)
+ clip_newer_than = models.DateTimeField(default=datetime.utcfromtimestamp(1))
+
+
+class AllowedChannel(models.Model):
+ broadcaster_id = models.CharField(max_length=100)
+ reset_data = models.ForeignKey(ResetData, on_delete=models.CASCADE)
+
+ class Meta:
+ unique_together = ('broadcaster_id', 'reset_data',)
class Clip(models.Model):
"""
import requests
import datetime
-from .errors import TooManyClips
+import pytz
+from .errors import TooManyClipsError, TooLateError, ChannelNotAllowedError, UserNotCreatedClipError, ClipTooOldError
from .models import Clip, ResetData
from urllib.parse import urlparse
-from allauth.socialaccount.models import SocialApp, SocialToken
+from allauth.socialaccount.models import SocialApp, SocialToken, SocialAccount
from django.contrib.auth.models import User
user = User.objects.get(id=user.id)
reset_data = ResetData.objects.latest('date_time')
reset_time = reset_data.date_time
- print(reset_time)
max_clips = reset_data.max_clips
+ if reset_data.end_date_time < datetime.datetime.now(pytz.utc):
+ raise TooLateError
+
if (
len(
Clip.objects.filter(account=user).filter(
)
>= max_clips
):
- raise TooManyClips
+ raise TooManyClipsError
social_app: SocialApp = SocialApp.objects.first()
oauth = SocialToken.objects.first().token
raise Exception
data = r.json()["data"][0]
- print(data)
+
+ if reset_data.user_created_clip:
+ if not SocialAccount.objects.get(user=user).uid == data["creator_id"]:
+ raise UserNotCreatedClipError
+
+ if reset_data.allowedchannel_set.count() != 0:
+ allowed_channels = reset_data.allowedchannel_set.filter(broadcaster_id=data["broadcaster_id"])
+ if not allowed_channels.exists():
+ raise ChannelNotAllowedError
+
+ if (
+ reset_data.clip_newer_than
+ > datetime.datetime.strptime(data["created_at"], "%Y-%m-%dT%H:%M:%S%z")
+ ):
+ raise ClipTooOldError
+
clip = Clip(
id=data["id"],
url=data["url"],
thumbnail_url=data["thumbnail_url"],
duration=data["duration"],
vod_offset=data["vod_offset"],
- date_added=datetime.datetime.now(),
+ date_added=datetime.datetime.now(pytz.utc),
account=user,
)
clip.validate_unique()
from .request_clip import request_clip
from .forms import ClipForm, RankForm
-from .errors import TooManyClips
+from .errors import TooManyClipsError, TooLateError, ChannelNotAllowedError, UserNotCreatedClipError, ClipTooOldError
from .models import Clip, ResetData
def show_clips(request, id):
reset_data = ResetData.objects.latest('date_time')
reset_time = reset_data.date_time
- print(reset_time)
try:
- video = Clip.objects.filter(date_added__gt=reset_time)[id - 1]
+ video = Clip.objects.filter(
+ date_added__gt=reset_time
+ ).order_by("date_added")[id - 1]
except IndexError:
- print("hi")
return redirect(final_ranking)
if request.method == "POST":
form = RankForm(request.POST)
if form.is_valid():
- print(f"post: {id} | {form.cleaned_data['value']}")
video.rank = form.cleaned_data["value"]
video.save()
return redirect(show_clips, id=id + 1)
def final_ranking(request):
reset_data = ResetData.objects.latest('date_time')
reset_time = reset_data.date_time
- print(reset_time)
return render(request, "manager/final.html", context={
"videos": Clip.objects.filter(date_added__gt=reset_time),
"ranks": range(reset_data.ranks, 0, -1),
request_clip(user=request.user, clip=form.cleaned_data["clip"])
except ValidationError:
message = "Sorry, clip already exists. Please send another clip."
- return render(request, "manager/index.html", {"message": message})
- # return HttpResponse(b"<h1>Clip already exists</h1>")
- except TooManyClips:
+ except TooManyClipsError:
message = "Sorry, you have already reached the clip limit."
- return render(request, "manager/index.html", {"message": message})
- # return HttpResponse(b"<h1>You have submitted the maximum number of clips</h1>")
+ except TooLateError:
+ message = "Sorry, the deadline for posting has passed"
+ except ChannelNotAllowedError:
+ message = "Sorry, you're not allowed to send a clip from that channel."
+ except UserNotCreatedClipError:
+ message = "Sorry, you need to be the one who has created the clip."
+ except ClipTooOldError:
+ message = "Sorry, the clip is too old. Please send a newer clip."
except Exception:
message = "Something went wrong."
- return render(request, "manager/index.html", {"message": message})
- # return HttpResponse(b"<h1>NOPE</h1>")
- # process the data in form.cleaned_data as required
- # ...
- # redirect to a new URL:
- message = "Thank you for submitting a clip."
+ else:
+ message = "Thank you for submitting a clip."
return render(request, "manager/index.html", {"message": message})
- # return HttpResponseRedirect("/thanks/")
- else:
- print("invalid")
# if a GET (or any other method) we'll create a blank form
else: