Giter VIP home page Giter VIP logo

donation-tracker's Introduction

Django Donation Tracker

Requirements

  • Python 3.8 to 3.12
  • Django 4.2, or 5.0

Additionally, if you are planning on developing, and/or building the JS bundles yourself:

  • Node (only LTS versions are officially supported, currently 16 and 18)
  • yarn (npm i -g yarn)
  • pre-commit (pip install pre-commit)

If you need to isolate your development environment, some combination of direnv, pyenv, nvm, and/or asdf will be very helpful.

Deploying

This app shouldn't require any special treatment to deploy, though depending on which feature set you are using, extra steps will be required. You should be able to install it with pip, either from GitHub, or locally. e.g.

pip install git+https://github.com/GamesDoneQuick/donation-tracker.git@master

Or after downloading or checking out locally:

pip install ./donation-tracker

For further reading on what else your server needs to look like:

Docker should also work but support is still in the experimental phases.

Configuration

The Donation Tracker adds a few configuration options.

TRACKER_HAS_CELERY (deprecated alias: HAS_CELERY)

Type: bool

Default: False

Controls whether or not to try and use Celery. Certain tasks will be queued up as asynchronous if this setting is turned on, but it requires extra setup and for smaller events the performance impact is pretty minor.

TRACKER_GIANTBOMB_API_KEY (deprecated alias: GIANTBOMB_API_KEY)

Type: str

Default: ''

Used for the cache_giantbomb_info management command. See that command for further details.

TRACKER_PRIVACY_POLICY_URL (deprecated alias: PRIVACY_POLICY_URL)

Type: str

Default: ''

If present, shown on the Donation page. You should probably have one of these, but this README is not legal advice.

TRACKER_SWEEPSTAKES_URL (deprecated alias: SWEEPSTAKES_URL)

Type: str

Default: ''

If present, shown in several prize-related pages. This is REQUIRED if you offer any prizes from your events, and will disable a lot of prize functionality if it's not set. This is for legal reasons because it's very easy to run afoul of local sweepstakes laws. This README is not legal advice, however, so you should contact a lawyer before you give away prizes.

TRACKER_PAGINATION_LIMIT

Type: int

Default: 500

Allows you to override the number of results a user can fetch from the API at a single time, or will be returned by default. Attempting to set a limit= param in a search higher than this value will return an error instead.

TRACKER_LOGO

Type: str

Default: ''

Allows you to place a logo asset in the navbar for public facing pages.

TRACKER_ENABLE_BROWSABLE_API

Type: bool

Default: settings.DEBUG

Allows you to enable or disable the DRF browsable API renderer on the v2 endpoints. By default, it's disabled in production mode and enabled in development.

This can potentially override DRF's own explicit or default settings, but only in that it will remove the renderer in question if it's in the list.

Testing Your Deploy (WIP)

  • PayPal currently requires the receiver account to have IPNs turned on so that payment can be confirmed
    • The sandbox sends IPNs, so you should not need to use the IPN simulator unless you really want to
  • There is a Diagnostics page on the admin, accessible if you are a Django superuser, it will let you test or monitor various pieces of Tracker functionality, which can give you early hints that something isn't working right

Development Quick Start

Clone the Git repo and install it in edit mode:

  • git clone [email protected]:GamesDoneQuick/donation-tracker
  • pip install -e donation-tracker

Start up a new Django Project like the Django Tutorial.

  • pip install django~=5.0 (if you need a specific version of Django)
  • django-admin startproject tracker_development

Install remaining development dependencies:

  • cd donation-tracker
  • yarn
  • pre-commit install
  • pre-commit install --hook-type pre-push

Add the following apps to the INSTALLED_APPS section of tracker_development/settings.py:

    'channels',
    'post_office',
    'paypal.standard.ipn',
    'tracker',
    'rest_framework',
    'timezone_field',
    'ajax_select',
    'mptt',

To enable analytics tracking, add the following to the MIDDLEWARE section of tracker_development/settings.py:

    'tracker.analytics.middleware.AnalyticsMiddleware',

NOTE: The analytics middleware is only a client, and does not track any information locally. Instead, it expects an analytics server to be running and will simply send out HTTP requests to it when enabled. More information is available in tracker/analytics/README.md.

Add the following chunk somewhere in settings.py:

from tracker import ajax_lookup_channels
AJAX_LOOKUP_CHANNELS = ajax_lookup_channels.AJAX_LOOKUP_CHANNELS
ASGI_APPLICATION = 'tracker_development.routing.application'
CHANNEL_LAYERS = {'default': {'BACKEND': 'channels.layers.InMemoryChannelLayer'}}

# Only required if analytics tracking is enabled
TRACKER_ANALYTICS_INGEST_HOST = 'http://localhost:5000'
TRACKER_ANALYTICS_NO_EMIT = False
TRACKER_ANALYTICS_TEST_MODE = False
TRACKER_ANALYTICS_ACCESS_KEY = 'someanalyticsaccesskey or None'

Create a file next called routing.py next to settings.py and put the following in it:

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.urls import path

import tracker.routing

application = ProtocolTypeRouter({
    'websocket': AllowedHostsOriginValidator(
        AuthMiddlewareStack(
            URLRouter(
                [path('tracker/', URLRouter(tracker.routing.websocket_urlpatterns))]
            )
        )
    ),
})

Edit the tracker_development/urls.py file to look something like this:

from django.contrib import admin
from django.urls import path, include

import tracker.urls
import ajax_select.urls

urlpatterns = [
    path('admin/lookups/', include(ajax_select.urls)),
    path('admin/', admin.site.urls),
    path('tracker/', include(tracker.urls, namespace='tracker')),
]

In the main project folder:

  • python manage.py runserver

In a separate shell, in the donation-tracker folder:

  • yarn start

If everything boots up correctly, you should be able to visit the Index Page. Additionally, you should be able to open the Websocket Test Page and see the heartbeat. If the page loads but the pings don't work, Channels isn't set up correctly. The Channels Documentation may be helpful.

Contributing

This project uses pre-commit to run linters and other checks before every commit.

If you followed the instructions above, pre-commit should run the appropriate hooks every time you commit or push.

Note: You can bypass these checks by adding --no-verify when you commit or push, though this is highly discouraged in most cases. CI runs the same checks as the hooks do, and will cause pipeline to fail if you bypass a genuine failure.

donation-tracker's People

Contributors

aofengen avatar bcutler-work avatar bsstephan avatar coolmatty avatar dependabot-preview[bot] avatar dependabot[bot] avatar edmund-huber avatar faultyserver avatar goldbattle avatar hippocrates avatar jdeng89 avatar justanr avatar uraniumanchor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

donation-tracker's Issues

Commentators missing from runs

I'm working on a little Go library and Matrix bot which right now relies on parsing /schedule. I only recently discovered /tracker and it actually having an API which is fantastic compared to scraping the HTML.

In trying to transition my client and bot to using /tracker/api/v1/search?run&event=ID to get the schedule for an event, I've discovered one snafu. The API does not return the hosts/commentators for a run. The commentators field is always "". I do get this from /schedule so I imagine there is a way to get the info, but I can't figure it out.

In the same vein, I noticed deprecated_runners and the runners array instead, but the latter only returns the runner ID, which would result in me having to do a bajillion more queries. Is there any way, through a query param or otherwise, to get that information inlined instead? It's been close to a decade since I last worked on a Django codebase so I'm a little lost trying to figure this out.

I realise we're close to an event so just wanted to say Thank You for everything and Good Luck!

[FYI] This code is being included in a large code dataset without notice

Hi, I've noticed that GDQ code(more repos than this one, but I figured this was the best place to open this) is being included in a massive(67TB) AI training dataset called The Stack. Unfortunately, they have an opt-out consent mechanism(which isn't true consent but I digress), so if you want your organization's code to be removed, you can go to https://huggingface.co/spaces/bigcode/in-the-stack to see which repos are impacted and how to opt out.

If this isn't a concern for you folks, feel free to close this, I'm just not interested in seeing everything vacuummed up without consent by AI bros, especially free software that's made to help facilitate causes like GDQ's charity donations. Thanks for your amazing work throughout the years, and gave a great day!

P.S: I'm not a bot, if this somehow sounds like a bot wrote it. I'm human, I promise.

Broken class on donation page

When looking at the html I found one of the classes were broken on the donation page
image

It seems that its an issue with the variable commentstate on the templates/tracker/donation.html page

Broken links on Admin Home page

The links for Process Donations and Read Donations at the bottom of the Admin Home page are not correct after building the donation processing pages

Process Donations links to /admin/tracker/donation/process_donations instead of admin/tracker/event/ui/v2/${eventId}/processing/donations

Read Donations links to /admin/tracker/donation/read_donations instead of admin/tracker/event/ui/v2/${eventId}/processing/read

<td><a href="{% url 'admin:process_donations' %}">Process Donations</a></td>
</tr>
<tr>
<td><a href="{% url 'admin:read_donations' %}">Read Donations</a></td>
</tr>
seems to be the issue - manually changing those links to

      <tr>
        <td><a href="{% url 'admin:tracker_ui' extra='v2/1/processing/donations' %}">Process Donations</a></td>
      </tr>
      <tr>
        <td><a href="{% url 'admin:tracker_ui' extra='v2/1/processing/read' %}">Read Donations</a></td>
      </tr>

gets to the correct page, but requires changing the event id number for each new event

v2 API mostly returns HTTP 500s

Looking at the endpoints for v2, I get the following patterns:

tracker/ api/v2/ ^events/$ [name='event-list']
tracker/ api/v2/ ^events\.(?P<format>[a-z0-9]+)/?$ [name='event-list']
tracker/ api/v2/ ^events/(?P<pk>[^/.]+)/$ [name='event-detail']
tracker/ api/v2/ ^events/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='event-detail']
tracker/ api/v2/ ^runners/$ [name='runner-list']
tracker/ api/v2/ ^runners\.(?P<format>[a-z0-9]+)/?$ [name='runner-list']
tracker/ api/v2/ ^runners/(?P<pk>[^/.]+)/$ [name='runner-detail']
tracker/ api/v2/ ^runners/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='runner-detail']
tracker/ api/v2/ ^runs/$ [name='speedrun-list']
tracker/ api/v2/ ^runs\.(?P<format>[a-z0-9]+)/?$ [name='speedrun-list']
tracker/ api/v2/ ^runs/(?P<pk>[^/.]+)/$ [name='speedrun-detail']
tracker/ api/v2/ ^runs/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='speedrun-detail']
tracker/ api/v2/ ^$ [name='api-root']
tracker/ api/v2/ ^\.(?P<format>[a-z0-9]+)/?$ [name='api-root']
tracker/ api/v2/ api-auth/ login/ [name='login']
tracker/ api/v2/ api-auth/ logout/ [name='logout'] 

However, trying to request /events/ seems to always return an HTTP 500:

$ curl https://gamesdonequick.com/tracker/api/v2/events/ -H "Accept: application/json" -vv

< HTTP/2 500 
< date: Sat, 15 May 2021 12:03:19 GMT
< content-type: text/html; charset=utf-8
< vary: Accept-Language, Cookie
< content-language: en

Server done blowed up

Varying the "Accept" header doesn't seem to matter either.

I get the same for just about any /events endpoint, /runs/ times out and some of the /run/ endpoints seem to also just 500 across the board.

I tried it with a local copy of donation-tracker, and in that case doing a request like curl http://localhost:8000/tracker/api/v2/events/ -vv doesn't blow up:

*   Trying ::1:8000...
* connect to ::1 port 8000 failed: Connection refused
*   Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /tracker/api/v2/events/ HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.76.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Type: application/json
< Vary: Accept, Cookie
< Allow: GET, HEAD, OPTIONS
< X-Frame-Options: SAMEORIGIN
< Content-Length: 2
< 
* Connection #0 to host localhost left intact
[]

Once I add an event to the database, things start to blow up locally too:

  • /events/ returns:
    Exception Type: TemplateDoesNotExist
    Exception Value: rest_framework/api.html
  • /events.json or /events.json/ returns:
    Exception Type: TypeError at /tracker/api/v2/events.json
    Exception Value: list() got an unexpected keyword argument 'format'

Based on what I'm seeing, is the v2 API in a state where it's expected to work and be used?

[Feature Request] Jump to current time in /schedule

It would be very convenient for mobile users to be able to jump to the current time in the schedule instead of having to manually scroll. Highlighting the current run in the schedule would also make it much easier to determine at a glance.

I'm not sure if this repo is currently accepting PR's, but I would be glad to contribute!

Incentive amount allocated before changing donation amount invalidates settings

At /tracker/ui/donate, if a donation amount is set and then an incentive is selected, the incentive allocation could end up being greater than the donation amount if the donation amount gets changes. This results in the following error on the page:

Unable to update the settings, those are invalid: [Error: The value [25] being set falls outside of the minimumValue [0.00] and maximumValue [2.00] range set for this element]

Steps to reproduce:

  1. Navigate to /tracker/ui/donate (e.g. https://gamesdonequick.com/tracker/ui/donate/28)
  2. Enter a donation amount (e.g. $25.00)
  3. Under Incentives, select Add Incentives
  4. Select an incentive (e.g. a bonus game incentive, which will pre-allocate the donation amount to the incentive)
  5. Return to the donation amount and alter the amount so that the donation amount is less than the incentive amount. (e.g. backspace the 5 in 25 to change the value to 26. The value will temporarily be 2.)
  6. Notice that the donation form is replaced with an error message and a stacktrace (included below.

Stacktrace:
Error: Unable to update the settings, those are invalid: [Error: The value [50] being set falls outside of the minimumValue [0.00] and maximumValue [25.00] range set for this element] at Function.value (https://gamesdonequick.com/static/tracker/gen/tracker-tracker-cc34d87aaade3b948e1b.js:39:102542) at e.value (https://gamesdonequick.com/static/tracker/gen/tracker-tracker-cc34d87aaade3b948e1b.js:39:195909) at t.value (https://gamesdonequick.com/static/tracker/gen/tracker-tracker-cc34d87aaade3b948e1b.js:39:75611) at Ao (https://gamesdonequick.com/static/tracker/gen/tracker-tracker-cc34d87aaade3b948e1b.js:23:51474) at Xa (https://gamesdonequick.com/static/tracker/gen/tracker-tracker-cc34d87aaade3b948e1b.js:23:69469) at Cs (https://gamesdonequick.com/static/tracker/gen/tracker-tracker-cc34d87aaade3b948e1b.js:23:105897) at Al (https://gamesdonequick.com/static/tracker/gen/tracker-tracker-cc34d87aaade3b948e1b.js:23:90221) at Nl (https://gamesdonequick.com/static/tracker/gen/tracker-tracker-cc34d87aaade3b948e1b.js:23:90146) at Sl (https://gamesdonequick.com/static/tracker/gen/tracker-tracker-cc34d87aaade3b948e1b.js:23:87486) at https://gamesdonequick.com/static/tracker/gen/tracker-tracker-cc34d87aaade3b948e1b.js:23:45816

Router with basename is already registered

It seems like some routes (specifically these in /tracker/api/urls.py)

router.register(
    r'events/(?P<event_pk>[^/.]+)/' + path + r'/feed_(?P<feed>\w+)',
    viewset,
    **kwargs,
)

and

router.register(r'events/(?P<event_pk>[^/.]+)/' + path, viewset, **kwargs)

have some problems as I'm constantly running into a django.core.exceptions.ImproperlyConfigured exception with comment: Router with basename "bid" is already registered. Please provide a unique basename for viewset "<class 'tracker.api.views.bids.BidViewSet'>"

Now this seems to go away if you just comment the lines and most parts of the tracker seem to work, but unfortunately, this is a consistently reproducible issue that I couldn't find a way around.

Missing "can edit locked events" pemission causes tracker crash

This issue occurred regardless of the event in question being locked or unlocked. If a user with permission to change donations but not permission to edit locked events tried to hit save on a donation (whether or not a change was being made), the following error appeared:
tracker_error

Stack trace pointed to the following as the issue, where the event object had no locked attribute:

if not request.user.has_perm('tracker.can_edit_locked_events'):
event = form.cleaned_data.get('event', None)
# this is a truly degenerate case
# a user either has to be:
# - adding a new child to event N
# - changing an existing child to point to event N when it wasn't before
# in addition to the following two conditions:
# - event N was not locked when the user opened the form, but got locked before the user could save
# - was not caught by existing machinery (choice validation, etc)
if event.locked:
raise PermissionDenied

Running python 3.9.16 with django 3.2, if it makes a difference

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.