├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── _apis ├── __init__.py ├── admin.py ├── apps.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ └── marry_speak.py ├── models │ ├── __init__.py │ ├── aws.py │ ├── discourse.py │ ├── flaschentaschen.py │ ├── flickr.py │ ├── google_photos.py │ ├── hackspaceOS.py │ ├── hackspaceOS_functions │ │ ├── event_approve.py │ │ ├── event_create.py │ │ ├── event_delete.py │ │ ├── event_overlap.py │ │ ├── events_slider.py │ │ ├── image_upload.py │ │ ├── keyword_add.py │ │ ├── keyword_remove.py │ │ ├── load_more.py │ │ ├── meeting_create.py │ │ ├── meeting_duration.py │ │ ├── meeting_end.py │ │ ├── meeting_start.py │ │ ├── open_status.py │ │ ├── page.py │ │ ├── search.py │ │ └── translate.py │ ├── instagram.py │ ├── marryspeak.py │ ├── mediawiki.py │ ├── meetup.py │ ├── meetup_functions │ │ ├── one_guilde.py │ │ ├── one_space.py │ │ └── setup.py │ ├── notify.py │ ├── search.py │ ├── slack.py │ ├── telegram.py │ └── twitter.py ├── tests │ ├── __init__.py │ ├── test_aws.py │ ├── test_discourse.py │ ├── test_flickr.py │ ├── test_google_photos.py │ ├── test_instagram.py │ ├── test_mediawiki.py │ ├── test_meetup.py │ ├── test_search.py │ ├── test_telegram.py │ └── test_twitter.py ├── urls.py └── views │ ├── __init__.py │ ├── hackspace_os_api_view.py │ └── hackspaces_org_api_view.py ├── _database ├── __init__.py ├── admin.py ├── apps.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ ├── announce_events.py │ │ ├── publish_events.py │ │ └── update_database.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_event_boolean_online_meetup.py │ ├── 0003_auto_20200330_1452.py │ └── __init__.py ├── models │ ├── __init__.py │ ├── consensus.py │ ├── event_set.py │ ├── events.py │ ├── guildes.py │ ├── helper.py │ ├── machines.py │ ├── meetingnotes.py │ ├── persons.py │ ├── photos.py │ ├── projects.py │ ├── spaces.py │ └── wishes.py ├── tests │ ├── __init__.py │ ├── test_consensus.py │ ├── test_events.py │ ├── test_guildes.py │ ├── test_machines.py │ ├── test_meetingnotes.py │ ├── test_persons.py │ ├── test_photos.py │ ├── test_projects.py │ ├── test_spaces.py │ └── test_wishes.py └── urls.py ├── _readme_images ├── headerimage.jpg ├── heading_about.png ├── heading_consensus.png ├── heading_contribute.png ├── heading_customize.png ├── heading_donate.png ├── heading_events.png ├── heading_examples.png ├── heading_features.png ├── heading_landingpage.png ├── heading_led_darkmode.png ├── heading_meeting_notes.png ├── heading_multi_language.png ├── heading_photos.png ├── heading_projects.png ├── heading_search.png ├── heading_setup.png ├── heading_spaces.png ├── heading_template_name.png ├── patreon_button.svg ├── screenshot_1.png ├── screenshot_about.png ├── screenshot_consensus.png ├── screenshot_donate.png ├── screenshot_events.png ├── screenshot_landingpage.png ├── screenshot_led_dark_mode.png ├── screenshot_meeting_notes.png ├── screenshot_multi_language.png ├── screenshot_photos.png ├── screenshot_projects.png ├── screenshot_search.png └── screenshot_spaces_machines.png ├── _setup ├── __init__.py ├── config_template.json ├── cronjobs.txt ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ └── setup.py ├── meeting_notes_template.txt ├── models │ ├── __init__.py │ ├── config.py │ ├── cronjobs.py │ ├── secrets.py │ ├── setup.py │ ├── setup_functions │ │ ├── __init__.py │ │ ├── delete.py │ │ ├── export.py │ │ ├── import_setup.py │ │ ├── menu.py │ │ ├── new.py │ │ └── new_functions │ │ │ ├── __init__.py │ │ │ ├── event_footer.py │ │ │ ├── languages.py │ │ │ ├── latlon_timezone.py │ │ │ ├── location.py │ │ │ └── riseuppad.py │ └── startup.py ├── secrets_template.json └── tests │ ├── test_new_setup.json │ └── test_setup.py ├── _translations ├── donate.html ├── events.html ├── landingpage.html ├── languages.json ├── meetings.html ├── menu.html ├── photos.html ├── results_lists.html └── values.html ├── _website ├── __init__.py ├── admin.py ├── apps.py ├── management │ ├── __init__.py │ └── commands │ │ └── __init__.py ├── models │ ├── __init__.py │ ├── request.py │ └── response.py ├── settings.py ├── static │ ├── css │ │ ├── animations.css │ │ ├── body.css │ │ ├── buttons.css │ │ ├── consensus.css │ │ ├── divider.css │ │ ├── event_new.css │ │ ├── event_page.css │ │ ├── event_slider.css │ │ ├── fonts.css │ │ ├── footer.css │ │ ├── header.css │ │ ├── landingpage.css │ │ ├── map.css │ │ ├── meetings.css │ │ ├── overlays.css │ │ ├── photos.css │ │ └── result_preview.css │ ├── images │ │ ├── Liked.svg │ │ ├── areas │ │ │ ├── 3d-printer.svg │ │ │ ├── electric-guitar.svg │ │ │ ├── game-controller.svg │ │ │ ├── group.svg │ │ │ ├── handsaw.svg │ │ │ ├── laser-cutting-machine.svg │ │ │ ├── programming.svg │ │ │ ├── robot.svg │ │ │ ├── soldering-iron.svg │ │ │ ├── tools.svg │ │ │ ├── whiteboard.svg │ │ │ └── yarn-ball.svg │ │ ├── donate │ │ │ ├── Hardware.svg │ │ │ ├── Money.svg │ │ │ ├── OrganizeEvent.svg │ │ │ ├── Patreon.svg │ │ │ ├── Volunteer.svg │ │ │ └── cat.png │ │ ├── event_default_image.jpeg │ │ ├── events │ │ │ ├── event_class.png │ │ │ ├── event_gaming.png │ │ │ ├── event_music.png │ │ │ └── event_sewing.png │ │ ├── footer │ │ │ ├── hackerspace_map.jpg │ │ │ └── social_media │ │ │ │ ├── facebook.svg │ │ │ │ ├── github.svg │ │ │ │ ├── instagram.svg │ │ │ │ ├── meetup.svg │ │ │ │ ├── patreon.svg │ │ │ │ ├── telegram.svg │ │ │ │ ├── twitter.svg │ │ │ │ └── youtube.svg │ │ ├── menu_icon.svg │ │ ├── photo_gallery │ │ │ ├── flickr.png │ │ │ ├── google-photos.svg │ │ │ ├── instagram.png │ │ │ └── wiki.png │ │ ├── plus.svg │ │ ├── search │ │ │ ├── Group.svg │ │ │ ├── Machine.svg │ │ │ ├── Space.svg │ │ │ ├── consensus.svg │ │ │ ├── discourse.svg │ │ │ ├── event.svg │ │ │ ├── notes.svg │ │ │ ├── project.svg │ │ │ └── wiki.svg │ │ └── separator.svg │ └── js │ │ ├── axios.js │ │ ├── events.js │ │ ├── inspace.js │ │ ├── meeting.js │ │ ├── menu.js │ │ ├── overlays.js │ │ ├── search.js │ │ ├── tabs.js │ │ ├── text_carousel.js │ │ ├── translate.js │ │ └── videocall.js ├── templates │ ├── components │ │ ├── SVGs │ │ │ ├── email.html │ │ │ ├── phone.html │ │ │ ├── plus.html │ │ │ └── telegram.html │ │ ├── body │ │ │ ├── consensus_item_preview.html │ │ │ ├── consensus_items_entries.html │ │ │ ├── edit_this_page.html │ │ │ ├── event_new │ │ │ │ ├── form_elements │ │ │ │ │ ├── dropdown_field.html │ │ │ │ │ ├── expected_crowd_field.html │ │ │ │ │ ├── hosts_field.html │ │ │ │ │ ├── input_field.html │ │ │ │ │ ├── location_field.html │ │ │ │ │ ├── overlapping_events.html │ │ │ │ │ ├── publish_options_field.html │ │ │ │ │ ├── repeating_field.html │ │ │ │ │ ├── text_field.html │ │ │ │ │ ├── upload_image_field.html │ │ │ │ │ └── volunteers_field.html │ │ │ │ ├── hosts_search_results.html │ │ │ │ └── new_event_form.html │ │ │ ├── events_slider.html │ │ │ ├── landing_contact_us.html │ │ │ ├── landing_do_i_belong.html │ │ │ ├── landing_please_donate.html │ │ │ ├── landing_visit_us.html │ │ │ ├── meetings │ │ │ │ ├── current_meeting.html │ │ │ │ ├── meetings_list.html │ │ │ │ ├── next_meeting.html │ │ │ │ └── past_meetings.html │ │ │ ├── photos_list.html │ │ │ ├── quick_access_icons.html │ │ │ ├── result_preview_block.html │ │ │ ├── results_list_entries.html │ │ │ └── wish_preview.html │ │ ├── discourse │ │ │ └── event_post.html │ │ ├── footer.html │ │ ├── head │ │ │ ├── css.html │ │ │ ├── favicons.html │ │ │ ├── head.html │ │ │ ├── js.html │ │ │ └── meta.html │ │ ├── header │ │ │ ├── landingpage.html │ │ │ └── temporary_info.html │ │ ├── menu.html │ │ ├── overlays │ │ │ ├── donate.html │ │ │ ├── meeting_over.html │ │ │ └── temporary_info.html │ │ └── search │ │ │ ├── search_result.html │ │ │ └── search_results.html │ ├── consensus_view.html │ ├── event_banner_view.html │ ├── event_new_view.html │ ├── event_view.html │ ├── guilde_view.html │ ├── landingpage_view.html │ ├── machine_view.html │ ├── meeting_present.html │ ├── meeting_view.html │ ├── meetings_view.html │ ├── page.html │ ├── photos_view.html │ ├── results_list.html │ ├── space_view.html │ └── values_view.html ├── templatetags │ ├── __init__.py │ ├── array.py │ ├── config.py │ ├── css.py │ ├── js.py │ ├── secrets.py │ ├── socialnetworks.py │ ├── text.py │ └── translate.py ├── tests │ └── __init__.py ├── urls.py ├── views │ ├── __init__.py │ ├── consensus_view.py │ ├── events_view.py │ ├── guildes_view.py │ ├── handler_404_view.py │ ├── landingpage_view.py │ ├── logout_view.py │ ├── machines_view.py │ ├── meetings_view.py │ ├── photos_view.py │ ├── projects_view.py │ ├── spaces_view.py │ ├── values_view.py │ └── view.py └── wsgi.py ├── install.py ├── manage.py ├── requirements.txt └── uwsgi_params /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: glowingkitty # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: marcoEDU # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | uploads/ 2 | *.conf 3 | *.service 4 | uwsgi_params 5 | HackspaceOSVenv/ 6 | _apis/models/instagram/ 7 | systemd/ 8 | 9 | # setup files 10 | config.json 11 | config_temp_backup.json 12 | header_banner.jpg 13 | header_logo.jpg 14 | logo.svg 15 | apple-touch-icon.png 16 | favicon-16x16.png 17 | favicon-32x32.png 18 | favicon.ico 19 | geckodriver* 20 | 21 | config/ 22 | secrets.json 23 | secrets_temp_backup.json 24 | *.sketch 25 | staticfiles/ 26 | pyvenv/ 27 | .vscode/ 28 | 29 | # Byte-compiled / optimized / DLL files 30 | __pycache__/ 31 | *.py[cod] 32 | *$py.class 33 | 34 | # C extensions 35 | *.so 36 | 37 | # Distribution / packaging 38 | .Python 39 | build/ 40 | develop-eggs/ 41 | dist/ 42 | downloads/ 43 | eggs/ 44 | .eggs/ 45 | lib/ 46 | lib64/ 47 | parts/ 48 | sdist/ 49 | var/ 50 | wheels/ 51 | *.egg-info/ 52 | .installed.cfg 53 | *.egg 54 | MANIFEST 55 | 56 | # PyInstaller 57 | # Usually these files are written by a python script from a template 58 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 59 | *.manifest 60 | *.spec 61 | 62 | # Installer logs 63 | pip-log.txt 64 | pip-delete-this-directory.txt 65 | 66 | # Unit test / coverage reports 67 | setup_backup__* 68 | htmlcov/ 69 | .tox/ 70 | .coverage 71 | .coverage.* 72 | .cache 73 | nosetests.xml 74 | coverage.xml 75 | *.cover 76 | .hypothesis/ 77 | .pytest_cache/ 78 | 79 | # Translations 80 | *.mo 81 | *.pot 82 | 83 | # Django stuff: 84 | *.log 85 | local_settings.py 86 | *.sqlite3 87 | 88 | # Flask stuff: 89 | instance/ 90 | .webassets-cache 91 | 92 | # Scrapy stuff: 93 | .scrapy 94 | 95 | # Sphinx documentation 96 | docs/_build/ 97 | 98 | # PyBuilder 99 | target/ 100 | 101 | # Jupyter Notebook 102 | .ipynb_checkpoints 103 | 104 | # pyenv 105 | .python-version 106 | 107 | # celery beat schedule file 108 | celerybeat-schedule 109 | 110 | # SageMath parsed files 111 | *.sage.py 112 | 113 | # Environments 114 | .env 115 | .venv 116 | env/ 117 | venv/ 118 | ENV/ 119 | env.bak/ 120 | venv.bak/ 121 | 122 | # Spyder project settings 123 | .spyderproject 124 | .spyproject 125 | 126 | # Rope project settings 127 | .ropeproject 128 | 129 | # mkdocs documentation 130 | /site 131 | 132 | # mypy 133 | .mypy_cache/ 134 | .DS_Store 135 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Marco 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /_apis/__init__.py: -------------------------------------------------------------------------------- 1 | default_app_config = '_apis.apps.APIConfig' -------------------------------------------------------------------------------- /_apis/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # list classes that should be accessible via the admin interface 4 | -------------------------------------------------------------------------------- /_apis/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class APIConfig(AppConfig): 5 | name = '_apis' 6 | -------------------------------------------------------------------------------- /_apis/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_apis/management/__init__.py -------------------------------------------------------------------------------- /_apis/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_apis/management/commands/__init__.py -------------------------------------------------------------------------------- /_apis/management/commands/marry_speak.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from _apis.models.marryspeak import MarrySpeak 3 | 4 | 5 | class Command(BaseCommand): 6 | help = "Make Marry speak! (Noisebridge specific)" 7 | 8 | def add_arguments(self, parser): 9 | parser.add_argument('str_text', type=str) 10 | 11 | def handle(self, *args, **options): 12 | speak(text=options['str_text'], intro='') 13 | -------------------------------------------------------------------------------- /_apis/models/__init__.py: -------------------------------------------------------------------------------- 1 | # link the models locations 2 | from _apis.models.aws import Aws 3 | from _apis.models.discourse import Discourse 4 | from _apis.models.flaschentaschen import Flaschentaschen 5 | from _apis.models.flickr import Flickr 6 | from _apis.models.google_photos import GooglePhotos 7 | from _apis.models.hackspaceOS import HackspaceOS 8 | from _apis.models.instagram import Instagram 9 | from _apis.models.marryspeak import MarrySpeak 10 | from _apis.models.mediawiki import MediaWiki 11 | from _apis.models.meetup import Meetup 12 | from _apis.models.notify import Notify 13 | from _apis.models.search import Search 14 | from _apis.models.slack import Slack 15 | from _apis.models.telegram import Telegram 16 | from _apis.models.twitter import Twitter 17 | -------------------------------------------------------------------------------- /_apis/models/flaschentaschen.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from pyprintplus import Log 3 | 4 | 5 | class Flaschentaschen(): 6 | def __init__(self, show_log=True): 7 | self.logs = ['self.__init__'] 8 | self.show_log = show_log 9 | self.url = 'http://pegasus.noise:4444/api' 10 | self.help = 'https://www.noisebridge.net/Flaschen_Taschen' 11 | 12 | def log(self, text): 13 | self.logs.append(text) 14 | if self.show_log == True: 15 | Log().print('{}'.format(text)) 16 | 17 | def showText(self, text): 18 | try: 19 | self.log('showText()') 20 | requests.post(self.url+'/text', {'text': text}) 21 | except: 22 | self.log('-> ERROR: Couldnt talk to Flaschentaschen. Make sure to deactivate your VPN connection and be in the local Noisebridge network.') 23 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/event_approve.py: -------------------------------------------------------------------------------- 1 | class EventApprove(): 2 | def __init__(self, request=None): 3 | from _database.models import Event 4 | from _apis.models import Notify 5 | from django.http import JsonResponse 6 | from _setup.models import Config 7 | 8 | if not request or request.user.is_authenticated == False: 9 | response = JsonResponse( 10 | {'success': False, 'error': '--> Failed: User not logged in'}) 11 | response.status_code = 403 12 | elif not request.GET.get('str_slug', None) or Event.objects.filter(boolean_approved=False, str_slug=request.GET.get('str_slug', None)).exists() == False: 13 | response = JsonResponse( 14 | {'success': False, 'error': '--> Failed: Result not found'}) 15 | response.status_code = 404 16 | else: 17 | 18 | DOMAIN = Config('WEBSITE.DOMAIN').value 19 | # approve event and all upcoming ones 20 | event = Event.objects.filter( 21 | boolean_approved=False, str_slug=request.GET.get('str_slug', None)).first() 22 | 23 | upcoming_events = Event.objects.filter( 24 | boolean_approved=False, str_name_en_US=event.str_name_en_US).all() 25 | print('--> Approve all upcoming events') 26 | for event in upcoming_events: 27 | event.publish() 28 | 29 | # notify that event was approved and by who 30 | if 'HTTP_HOST' in request.META and request.META['HTTP_HOST'] == DOMAIN: 31 | Notify().send('✅'+str(request.user)+' approved the event "' + 32 | event.str_name_en_US+'":\nhttps://'+DOMAIN+'/'+event.str_slug) 33 | 34 | response = JsonResponse({'success': True}) 35 | response.status_code = 200 36 | 37 | self.value = response 38 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/event_delete.py: -------------------------------------------------------------------------------- 1 | class EventDelete(): 2 | def __init__(self, request=None): 3 | from _database.models import Event 4 | from _apis.models import Notify 5 | from _setup.models import Config 6 | from django.http import JsonResponse 7 | 8 | if not request.GET.get('str_slug', None) or Event.objects.filter(str_slug=request.GET.get('str_slug', None)).exists() == False: 9 | response = JsonResponse( 10 | {'success': False, 'error': '--> Failed: Result not found'}) 11 | response.status_code = 404 12 | else: 13 | 14 | # approve event and all upcoming ones 15 | event = Event.objects.filter( 16 | str_slug=request.GET.get('str_slug', None)).first() 17 | 18 | if event.boolean_approved and (not request or request.user.is_authenticated == False): 19 | response = JsonResponse( 20 | {'success': False, 'error': '--> Failed: User not logged in'}) 21 | response.status_code = 403 22 | 23 | else: 24 | print('--> Delete all upcoming events') 25 | event.delete_series() 26 | 27 | # notify via slack that event was deleted and by who 28 | if 'HTTP_HOST' in request.META and request.META['HTTP_HOST'] == Config('WEBSITE.DOMAIN').value: 29 | Notify().send('🚫'+str(request.user)+' deleted the event "' + 30 | event.str_name_en_US+'"') 31 | 32 | response = JsonResponse({'success': True}) 33 | response.status_code = 200 34 | 35 | self.value = response 36 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/event_overlap.py: -------------------------------------------------------------------------------- 1 | class EventOverlap(): 2 | def __init__(self, request): 3 | from _database.models import Event 4 | from django.http import JsonResponse 5 | from django.template.loader import get_template 6 | from _website.models import Request 7 | 8 | str_date = request.GET.get('date', None) 9 | str_time = request.GET.get('time', None) 10 | str_duration = request.GET.get('duration', None) 11 | if str_date and str_time and str_duration: 12 | from _database.models import Helper 13 | 14 | overlapping_events = Event.objects.JSON__overlapping_events( 15 | Helper().INT__UNIX_from_date_and_time_STR(str_date, str_time), 16 | Helper().INT__duration_minutes(str_duration), 17 | request.GET.get('space', None), 18 | ) 19 | 20 | self.value = JsonResponse({ 21 | 'int_overlapping_events': len(overlapping_events['overlapping_events']), 22 | 'html': get_template( 23 | 'components/body/event_new/form_elements/overlapping_events.html').render({ 24 | 'language': Request(request).language, 25 | 'overlapping_events': overlapping_events 26 | })}) 27 | else: 28 | self.value = JsonResponse({ 29 | 'error': 'Variables missing - date, time and duration needed.'}) 30 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/events_slider.py: -------------------------------------------------------------------------------- 1 | class EventsSlider(): 2 | def __init__(self, request): 3 | from django.http import JsonResponse 4 | from django.template.loader import get_template 5 | from _database.models import Event 6 | from _website.models import Request 7 | 8 | marry_messages = [] 9 | in_space = request.COOKIES.get('in_space') 10 | if request: 11 | request = Request(request) 12 | if in_space: 13 | events_in_5_minutes = Event.objects.LIST__in_minutes( 14 | minutes=5, name_only=True) 15 | events_in_30_minutes = Event.objects.LIST__in_minutes( 16 | minutes=30, name_only=True) 17 | if events_in_5_minutes or events_in_30_minutes: 18 | marry_messages.append('We have some awesome events upcoming') 19 | for event in events_in_5_minutes: 20 | marry_messages.append(event+' starts in 5 minutes.') 21 | for event in events_in_30_minutes: 22 | marry_messages.append(event+' starts in 30 minutes.') 23 | 24 | self.value = JsonResponse( 25 | { 26 | 'html': get_template( 27 | 'components/body/events_slider.html').render({ 28 | 'language': request.language, 29 | 'upcoming_events': Event.objects.QUERYSET__upcoming()[:5] 30 | }), 31 | 'marryspeak': marry_messages 32 | } 33 | ) 34 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/image_upload.py: -------------------------------------------------------------------------------- 1 | class ImageUpload(): 2 | def __init__(self, request=None): 3 | from django.http import JsonResponse 4 | from django.template.loader import get_template 5 | 6 | if request.FILES['images[0]'].content_type != 'image/jpeg' and request.FILES['images[0]'].content_type != 'image/png': 7 | response = JsonResponse({ 8 | 'notification': get_template('components/notification.html').render({ 9 | 'text_message': 'Please upload a JPG or PNG image.', 10 | 'str_icon': 'error' 11 | })}) 12 | response.status_code = 500 13 | 14 | else: 15 | from _apis.models import Aws 16 | 17 | image_s3_url = Aws().upload(request.FILES['images[0]']) 18 | 19 | if image_s3_url: 20 | response = JsonResponse({'url_image': image_s3_url}) 21 | else: 22 | response = JsonResponse( 23 | {'url_image': None, 'error': '--> AWS secrets are missing. Couldnt upload image.'}) 24 | 25 | self.value = response 26 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/keyword_add.py: -------------------------------------------------------------------------------- 1 | class KeywordAdd(): 2 | def __init__(self, keyword, request): 3 | from django.http import JsonResponse 4 | from _database.models import MeetingNote 5 | 6 | text_date = request.META['HTTP_REFERER'].split('/')[-1] 7 | if keyword and request.META['HTTP_REFERER'] and MeetingNote.objects.filter(text_date=text_date).exists(): 8 | meeting = MeetingNote.objects.filter(text_date=text_date).first() 9 | 10 | meeting.keyword_add(keyword) 11 | response = JsonResponse({'success': True}) 12 | else: 13 | response = JsonResponse({'error': 'Request incomplete or wrong'}) 14 | response.status_code = 404 15 | 16 | self.value = response 17 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/keyword_remove.py: -------------------------------------------------------------------------------- 1 | class KeywordRemove(): 2 | def __init__(self, keyword, request): 3 | from django.http import JsonResponse 4 | from _database.models import MeetingNote 5 | 6 | text_date = request.META['HTTP_REFERER'].split('/')[-1] 7 | if keyword and request.META['HTTP_REFERER'] and MeetingNote.objects.filter(text_date=text_date).exists(): 8 | meeting = MeetingNote.objects.filter(text_date=text_date).first() 9 | 10 | meeting.keyword_remove(keyword) 11 | response = JsonResponse({'success': True}) 12 | else: 13 | response = JsonResponse({'error': 'Request incomplete or wrong'}) 14 | response.status_code = 404 15 | 16 | self.value = response 17 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/load_more.py: -------------------------------------------------------------------------------- 1 | class LoadMore(): 2 | def __init__(self, what, request): 3 | from django.http import JsonResponse 4 | from _database.models import Helper, MeetingNote, Event, Project, Space, Machine, Guilde, Consensus 5 | if what and request.GET.get('from', None): 6 | if what == 'meeting_notes': 7 | response = Helper().JSON_RESPONSE_more_results( 8 | request, 'meetings/meetings_list.html', MeetingNote.objects.past()) 9 | elif what == 'events': 10 | response = Helper().JSON_RESPONSE_more_results( 11 | request, 'results_list_entries.html', Event.objects.QUERYSET__upcoming()) 12 | elif what == 'projects': 13 | response = Helper().JSON_RESPONSE_more_results( 14 | request, 'results_list_entries.html', Project.objects.latest()) 15 | elif what == 'spaces': 16 | response = Helper().JSON_RESPONSE_more_results( 17 | request, 'results_list_entries.html', Space.objects.all()) 18 | elif what == 'machines': 19 | response = Helper().JSON_RESPONSE_more_results( 20 | request, 'results_list_entries.html', Machine.objects.all()) 21 | elif what == 'guildes': 22 | response = Helper().JSON_RESPONSE_more_results( 23 | request, 'results_list_entries.html', Guilde.objects.all()) 24 | elif what == 'consensus': 25 | response = Helper().JSON_RESPONSE_more_results( 26 | request, 'consensus_items_entries.html', Consensus.objects.latest()) 27 | elif what == 'photos': 28 | response = Helper().JSON_RESPONSE_more_photos(request) 29 | else: 30 | response = JsonResponse({'error': 'Request incomplete or wrong'}) 31 | response.status_code = 404 32 | 33 | self.value = response 34 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/meeting_create.py: -------------------------------------------------------------------------------- 1 | class MeetingCreate(): 2 | def __init__(self, request): 3 | from _database.models import MeetingNote 4 | from django.http import JsonResponse 5 | from django.template.loader import get_template 6 | from _website.models import Request 7 | 8 | new_meeting = MeetingNote() 9 | new_meeting.save() 10 | 11 | self.value = JsonResponse( 12 | { 13 | 'success': True, 14 | 'html': get_template( 15 | 'components/body/meetings/current_meeting.html').render({ 16 | 'language': Request(request).language, 17 | 'current_meeting': new_meeting 18 | }) 19 | } 20 | ) 21 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/meeting_duration.py: -------------------------------------------------------------------------------- 1 | class MeetingDuration(): 2 | def __init__(self, request): 3 | from django.http import JsonResponse 4 | from _database.models import MeetingNote 5 | from _website.models import Request 6 | marry_messages = [] 7 | meeting = MeetingNote.objects.current() 8 | running_since = meeting.running_since if meeting else None 9 | if Request(request).in_space: 10 | if running_since == '1h 30min': 11 | marry_messages.append( 12 | 'Thanks everyone for partipicating in the weekly meeting. The meeting is going on now for 1 hour and 30 minutes') 13 | elif running_since == '2h 30min': 14 | marry_messages.append( 15 | 'I always love people actively discussion topics related to Noisebridge. However, it seems the meeting is going on now for 2 hours and 30 minutes. Please come to an end soon') 16 | 17 | self.value = JsonResponse( 18 | { 19 | 'html': running_since, 20 | 'marryspeak': marry_messages 21 | }) 22 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/meeting_end.py: -------------------------------------------------------------------------------- 1 | class MeetingEnd(): 2 | def __init__(self, request): 3 | from _database.models import MeetingNote 4 | from django.http import JsonResponse 5 | 6 | current_meeting = MeetingNote.objects.current() 7 | if current_meeting: 8 | current_meeting.end() 9 | response = JsonResponse( 10 | {'meeting_url': '/meeting/'+current_meeting.text_date}) 11 | 12 | else: 13 | response = JsonResponse({'alert': 'No current meeting found'}) 14 | response.status_code = 500 15 | 16 | self.value = response 17 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/meeting_start.py: -------------------------------------------------------------------------------- 1 | class MeetingStart(): 2 | def __init__(self, request): 3 | from django.http import JsonResponse 4 | from django.template.loader import get_template 5 | from _website.models import Request 6 | 7 | self.value = JsonResponse( 8 | { 9 | 'success': True, 10 | 'html': get_template( 11 | 'components/body/meetings/current_meeting.html').render({ 12 | 'language': Request(request).language, 13 | }) 14 | } 15 | ) 16 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/search.py: -------------------------------------------------------------------------------- 1 | class Search(): 2 | def __init__(self, request): 3 | from django.http import JsonResponse 4 | from _apis.models import Search 5 | from _website.models import Request 6 | from django.template.loader import get_template 7 | 8 | language = Request(request).language 9 | search_results = Search().query(request.GET.get( 10 | 'q', None), request.GET.get('filter', None)) 11 | self.value = JsonResponse( 12 | { 13 | 'num_results': len(search_results), 14 | 'html': get_template( 15 | 'components/search/search_results.html').render({ 16 | 'language': language, 17 | 'search_results': search_results 18 | }) if not request.GET.get('filter', None) else get_template('components/body/event_new/hosts_search_results.html').render({ 19 | 'language': language, 20 | 'all_hosts': search_results[:4], 21 | }) if request.GET.get('filter', None) == 'hosts' else get_template('components/body/results_list_entries.html').render({ 22 | 'language': language, 23 | 'all_results': search_results[:4], 24 | }), 25 | } 26 | ) 27 | -------------------------------------------------------------------------------- /_apis/models/hackspaceOS_functions/translate.py: -------------------------------------------------------------------------------- 1 | class Translate(): 2 | def __init__(self, request=None): 3 | from django.http import JsonResponse 4 | import json 5 | import bleach 6 | from googletrans import Translator 7 | import emoji 8 | from _setup.models import Config 9 | translator = Translator() 10 | 11 | with open('_translations/languages.json') as json_file: 12 | language_codes = json.load(json_file) 13 | 14 | if request.GET.get('q', None) and request.GET.get('language', None): 15 | text = emoji.get_emoji_regexp().sub(u'', request.GET.get('q', None)) 16 | 17 | response = JsonResponse({'text': translator.translate( 18 | text=text, 19 | dest=request.GET.get('language', None)).text 20 | }) 21 | 22 | elif request.GET.get('q', None): 23 | LANGUAGES = Config('WEBSITE.LANGUAGES').value 24 | languages = {} 25 | 26 | text = emoji.get_emoji_regexp().sub(u'', request.GET.get('q', None)) 27 | 28 | for language in LANGUAGES: 29 | if len(LANGUAGES) > 1: 30 | languages[language] = translator.translate( 31 | text=text, 32 | dest=language_codes[language]).text 33 | else: 34 | languages[language] = request.GET.get('q', None) 35 | 36 | response = JsonResponse(languages) 37 | 38 | else: 39 | response = JsonResponse({'error': 'fields missing'}) 40 | response.status_code = 404 41 | 42 | self.value = response 43 | -------------------------------------------------------------------------------- /_apis/models/meetup.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | 4 | import requests 5 | from MeetupAPI import Meetup 6 | 7 | from _setup.models import Config, Secret 8 | 9 | 10 | class Meetup(Meetup): 11 | def __init__(self, 12 | group=Config('EVENTS.MEETUP_GROUP').value, 13 | email=Secret('MEETUP.EMAIL').value, 14 | password=Secret('MEETUP.PASSWORD').value, 15 | client_id=Secret('MEETUP.CLIENT_ID').value, 16 | client_secret=Secret('MEETUP.CLIENT_SECRET').value, 17 | redirect_uri=Secret('MEETUP.REDIRECT_URI').value, 18 | show_log=True, 19 | test=False): 20 | self.show_log = show_log 21 | self.group = group 22 | self.email = email 23 | self.password = password 24 | self.client_id = client_id 25 | self.client_secret = client_secret, 26 | self.redirect_uri = redirect_uri 27 | 28 | self.default_space_name = Config('BASICS.NAME').value 29 | HACKERSPACE_ADDRESS = Config('PHYSICAL_SPACE.ADDRESS').value 30 | self.default_space_address = { 31 | "STREET": HACKERSPACE_ADDRESS['STREET'], 32 | "ZIP": HACKERSPACE_ADDRESS['ZIP'], 33 | "CITY": HACKERSPACE_ADDRESS['CITY'], 34 | "COUNTRYCODE": HACKERSPACE_ADDRESS['COUNTRYCODE'], 35 | } 36 | self.default_space_how_to_find_us = Config( 37 | 'PHYSICAL_SPACE.ADDRESS.HOW_TO_FIND_US__english').value 38 | self.default_space_timezonestring = Config( 39 | 'PHYSICAL_SPACE.TIMEZONE_STRING').value 40 | 41 | self.test = test 42 | 43 | def setup(self): 44 | from _apis.models.meetup_functions.setup import MeetupSetup 45 | MeetupSetup(self.group, self.test) 46 | 47 | def one_space(self, event): 48 | from _apis.models.meetup_functions.one_space import MeetupOneSpace 49 | return MeetupOneSpace(event).value 50 | 51 | def one_guilde(self, event): 52 | from _apis.models.meetup_functions.one_guilde import MeetupOneGuilde 53 | return MeetupOneGuilde(event).value 54 | -------------------------------------------------------------------------------- /_apis/models/meetup_functions/one_guilde.py: -------------------------------------------------------------------------------- 1 | from _setup.models import Config 2 | 3 | 4 | class MeetupOneGuilde(): 5 | def __init__(self, event): 6 | from _database.models import Guilde 7 | 8 | EVENTS_GUILDES_OVERWRITE = Config( 9 | 'EVENTS.EVENTS_GUILDES_OVERWRITE').value 10 | 11 | for str_keyword in EVENTS_GUILDES_OVERWRITE: 12 | if str_keyword in event['name']: 13 | self.value = Guilde.objects.filter( 14 | str_name_en_US=EVENTS_GUILDES_OVERWRITE[str_keyword]).first() 15 | else: 16 | self.value = None 17 | -------------------------------------------------------------------------------- /_apis/models/meetup_functions/one_space.py: -------------------------------------------------------------------------------- 1 | from _setup.models import Config 2 | 3 | 4 | class MeetupOneSpace(): 5 | def __init__(self, event): 6 | from _database.models import Space 7 | 8 | if 'how_to_find_us' in event: 9 | spaces = Space.objects.all() 10 | 11 | for space in spaces.iterator(): 12 | if space.str_name_en_US.lower() in event['how_to_find_us'].lower(): 13 | self.value = space 14 | 15 | # else... 16 | EVENTS_SPACES_OVERWRITE = Config( 17 | 'EVENTS.EVENTS_SPACES_OVERWRITE').value 18 | for field in EVENTS_SPACES_OVERWRITE: 19 | if field in event['name']: 20 | self.value = Space.objects.QUERYSET__by_name( 21 | EVENTS_SPACES_OVERWRITE[field]) 22 | else: 23 | self.value = Space.objects.QUERYSET__by_name( 24 | Config('EVENTS.EVENTS_SPACE_DEFAULT').value) 25 | -------------------------------------------------------------------------------- /_apis/models/notify.py: -------------------------------------------------------------------------------- 1 | from pyprintplus import Log 2 | import time 3 | 4 | 5 | class Notify(): 6 | def __init__(self, show_log=True, test=False): 7 | self.logs = ['self.__init__'] 8 | self.show_log = show_log 9 | self.started = round(time.time()) 10 | self.test = test 11 | 12 | @property 13 | def setup_done(self): 14 | from _apis.models import Slack, Telegram 15 | return True if Slack().setup_done or Telegram().setup_done else False 16 | 17 | @property 18 | def config(self): 19 | from _apis.models import Slack, Telegram 20 | if Slack().setup_done: 21 | return {"selected": "Slack", "config": Slack().config} 22 | elif Telegram().setup_done: 23 | return {"selected": "Telegram", "config": Telegram().config} 24 | else: 25 | return {} 26 | 27 | def log(self, text): 28 | import os 29 | self.logs.append(text) 30 | if self.show_log == True: 31 | Log().print('{}'.format(text), os.path.basename(__file__), self.started) 32 | 33 | def setup(self): 34 | from pyprintplus import Log 35 | from _apis.models import Slack, Telegram 36 | try: 37 | if not Slack().setup_done and not Telegram().setup_done: 38 | Log().show_messages( 39 | ['Let\'s setup notifications for your new website!']) 40 | 41 | Slack(test=self.test).setup() 42 | 43 | if not Slack().setup_done and not Telegram().setup_done: 44 | Telegram(test=self.test).setup() 45 | 46 | Log().show_message('Notify setup complete.') 47 | except KeyboardInterrupt: 48 | Log().show_message('Ok, canceled setup.') 49 | 50 | def send(self, message): 51 | self.log('send()') 52 | from _apis.models import Slack, Telegram 53 | 54 | if Slack().setup_done: 55 | return Slack().message(message) 56 | elif Telegram().setup_done: 57 | return Telegram().message(message) 58 | else: 59 | self.log('-> ERROR: Notify setup not completed') 60 | -------------------------------------------------------------------------------- /_apis/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_apis/tests/__init__.py -------------------------------------------------------------------------------- /_apis/tests/test_aws.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _apis.models import Aws 3 | 4 | 5 | class AwsTestCase(TestCase): 6 | def test_s3_upload_and_delete(self): 7 | if Aws().setup_done: 8 | with open('README.md', 'rb') as f: 9 | file_url = Aws().upload(f) 10 | self.assertTrue(type(file_url) == str) 11 | Aws().delete('README.md') 12 | -------------------------------------------------------------------------------- /_apis/tests/test_discourse.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _apis.models import Discourse 3 | 4 | 5 | class DiscourseTestCase(TestCase): 6 | def test_search(self): 7 | search_results = Discourse().search('3d print') 8 | self.assertTrue(len(search_results) > 0) 9 | self.assertTrue(search_results[0]['name']) 10 | 11 | def test_create_and_delete_post(self): 12 | new_post_url = Discourse().create_post('This is an automated test', 13 | 'Unittests are awesome.', 'events') 14 | self.assertTrue(type(new_post_url) == str) 15 | self.assertTrue(Discourse().delete_post(new_post_url) == True) 16 | 17 | def test_get_categories(self): 18 | categories = Discourse().get_categories() 19 | self.assertTrue(type(categories) == list) 20 | self.assertTrue(len(categories) > 0) 21 | 22 | def test_get_category_id(self): 23 | category_id = Discourse().get_category_id('events') 24 | self.assertTrue(category_id == None or type(category_id) == int) 25 | 26 | def test_get_category_posts(self): 27 | self.assertTrue(type(Discourse().get_category_posts('events')) == list) 28 | 29 | def test_get_post_details(self): 30 | # get a post 31 | categories = Discourse().get_categories() 32 | posts = Discourse().get_category_posts(categories[0]) 33 | slug = posts[0]['slug'] 34 | post_details = Discourse().get_post_details(slug) 35 | self.assertTrue('id' in post_details) 36 | self.assertTrue('cooked' in post_details) 37 | 38 | def test_get_users(self): 39 | users = Discourse().get_users() 40 | self.assertTrue(type(users) == list) 41 | self.assertTrue('user' in users[0]) 42 | -------------------------------------------------------------------------------- /_apis/tests/test_flickr.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | from _apis.models import Flickr 4 | 5 | 6 | class FlickrTestCase(TestCase): 7 | def test_photos(self): 8 | photos = Flickr( 9 | 'https://www.flickr.com/groups/noisebridge/pool/', test=True).photos 10 | self.assertTrue(len(photos) > 0) 11 | self.assertTrue(len(photos[0]['URL_image']) > 20) 12 | self.assertTrue(len(photos[0]['URL_post']) > 20) 13 | self.assertTrue(photos[0]['INT_UNIX_taken'] != None) 14 | -------------------------------------------------------------------------------- /_apis/tests/test_google_photos.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _apis.models import GooglePhotos 3 | 4 | 5 | class GooglePhotosTestCase(TestCase): 6 | def test_photos(self): 7 | GooglePhotos( 8 | ['https://photos.google.com/share/AF1QipNdUmxDzWRLtsxIcWIugAjr5gN_GBPd18XpfSkeSWteXPwqJC-c5_HTYjy-dQJPXQ?key=WVA4ekpWZE1HMlNvdzdSVkJGLS1yZTZaQ1Q3bW13'], test=True).import_photos() 9 | -------------------------------------------------------------------------------- /_apis/tests/test_instagram.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _apis.models import Instagram 3 | 4 | 5 | class InstagramTestCase(TestCase): 6 | def test_photos(self): 7 | photos = Instagram('noisebridgehackerspace', 8 | '#noisebridgehackerspace').photos 9 | self.assertTrue(len(photos) > 0) 10 | self.assertTrue(len(photos[0]['URL_image']) > 20) 11 | self.assertTrue(len(photos[0]['URL_post']) > 20) 12 | self.assertTrue(photos[0]['INT_UNIX_taken'] != None) 13 | -------------------------------------------------------------------------------- /_apis/tests/test_mediawiki.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _apis.models import MediaWiki 3 | 4 | 5 | class MediaWikiTestCase(TestCase): 6 | def test_seach(self): 7 | search_results = MediaWiki().search('electronic') 8 | self.assertTrue(type(search_results) == list) 9 | self.assertTrue(len(search_results) == 10 | 0 or 'name' in search_results[0]) 11 | -------------------------------------------------------------------------------- /_apis/tests/test_meetup.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from django.test import TestCase 4 | 5 | from _apis.models import Meetup 6 | from _database.models import Event 7 | 8 | 9 | class MeetupTestCase(TestCase): 10 | def setUp(self): 11 | Event.objects.import_from_meetup(slug='noisebridge') 12 | 13 | def test_events(self): 14 | events = Meetup('noisebridge').events(maximum_num_events=50) 15 | self.assertTrue(len(events) > 0) 16 | self.assertTrue(events[0]['str_name_en_US'] != None) 17 | self.assertTrue(events[0]['url_meetup_event'] != None) 18 | 19 | def test_create_and_delete(self): 20 | event = Event.objects.all()[0] 21 | int_start_time = event.int_UNIXtime_event_start 22 | event.int_UNIXtime_event_start = round(time.time()+600) 23 | 24 | event = Meetup().create(event=event, publish_status='draft') 25 | self.assertTrue(event.url_meetup_event != None) 26 | 27 | event = Meetup().delete(event=event) 28 | event.int_UNIXtime_event_start = int_start_time 29 | self.assertTrue(event.url_meetup_event == None) 30 | -------------------------------------------------------------------------------- /_apis/tests/test_search.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _apis.models import Search 3 | 4 | 5 | class SearchTestCase(TestCase): 6 | def test_query(self): 7 | search_results = Search().query('electronic') 8 | self.assertTrue(type(search_results) == list) 9 | self.assertTrue(len(search_results) == 10 | 0 or 'name' in search_results[0]) 11 | -------------------------------------------------------------------------------- /_apis/tests/test_telegram.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _apis.models import Telegram 3 | from _setup.models import Config 4 | from random import randint 5 | 6 | 7 | class TelegramTestCase(TestCase): 8 | def test_message(self): 9 | if Telegram().setup_done: 10 | messages = Config('UNITTESTS.TELEGRAM_TEST_MESSAGES').value 11 | selected_message = randint(0, len(messages)-1) 12 | response = Telegram().message(messages[selected_message]) 13 | self.assertEqual(response, True) 14 | -------------------------------------------------------------------------------- /_apis/tests/test_twitter.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _apis.models import Twitter 3 | 4 | 5 | class TwitterTestCase(TestCase): 6 | def test_photos(self): 7 | photos = Twitter('noisebridge', '#noisebridge').photos 8 | self.assertTrue(len(photos) > 0) 9 | self.assertTrue(len(photos[0]['URL_image']) > 20) 10 | self.assertTrue(len(photos[0]['URL_post']) > 20) 11 | self.assertTrue(photos[0]['INT_UNIX_taken'] != None) 12 | -------------------------------------------------------------------------------- /_apis/views/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_apis/views/__init__.py -------------------------------------------------------------------------------- /_apis/views/hackspace_os_api_view.py: -------------------------------------------------------------------------------- 1 | from _website.views.view import View 2 | from _apis.models import HackspaceOS 3 | 4 | 5 | class HackspaceOSapiView(View): 6 | def post(self, request, sub_page=None): 7 | if self.path == 'image_upload': 8 | return HackspaceOS().image_upload(request) 9 | 10 | elif self.path == 'event_create': 11 | return HackspaceOS().event_create(request) 12 | 13 | def get(self, request, sub_page=None): 14 | if self.path == 'page' and sub_page: 15 | return HackspaceOS().page(sub_page, request) 16 | 17 | elif self.path == 'load_more' and sub_page: 18 | return HackspaceOS().load_more(sub_page, request) 19 | 20 | elif self.path == 'open_status': 21 | return HackspaceOS().open_status(request) 22 | 23 | elif self.path == 'translate': 24 | return HackspaceOS().translate(request) 25 | 26 | elif self.path == 'search': 27 | return HackspaceOS().search(request) 28 | 29 | elif self.path == 'keyword_remove': 30 | return HackspaceOS().keyword_remove(sub_page, request) 31 | 32 | elif self.path == 'keyword_add': 33 | return HackspaceOS().keyword_add(sub_page, request) 34 | 35 | elif self.path == 'events_slider': 36 | return HackspaceOS().events_slider(request) 37 | 38 | elif self.path == 'event_approve': 39 | return HackspaceOS().event_approve(request) 40 | 41 | elif self.path == 'event_delete': 42 | return HackspaceOS().event_delete(request) 43 | 44 | elif self.path == 'event_overlap': 45 | return HackspaceOS().event_overlap(request) 46 | 47 | elif self.path == 'meeting_duration': 48 | return HackspaceOS().meeting_duration(request) 49 | 50 | elif self.path == 'meeting_start': 51 | return HackspaceOS().meeting_start(request) 52 | 53 | elif self.path == 'meeting_create': 54 | return HackspaceOS().meeting_create(request) 55 | 56 | elif self.path == 'meeting_end': 57 | return HackspaceOS().meeting_end(request) 58 | -------------------------------------------------------------------------------- /_apis/views/hackspaces_org_api_view.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from django.views import View 3 | 4 | 5 | class HackspacesORGapiView(View): 6 | greeting = "Good Day" 7 | 8 | def get(self, request): 9 | return HttpResponse(self.greeting) 10 | -------------------------------------------------------------------------------- /_database/__init__.py: -------------------------------------------------------------------------------- 1 | default_app_config = '_database.apps.DatabaseConfig' -------------------------------------------------------------------------------- /_database/admin.py: -------------------------------------------------------------------------------- 1 | from _database.models import Event,Space,Machine,Project,Guilde,Consensus 2 | from django.contrib import admin 3 | 4 | 5 | class AuthorAdmin(admin.ModelAdmin): 6 | exclude = ('str_slug', 'int_UNIXtime_created', 'int_UNIXtime_updated',) 7 | 8 | 9 | # Register your models here. 10 | admin.site.register(Event, AuthorAdmin) 11 | admin.site.register(Project, AuthorAdmin) 12 | admin.site.register(Guilde, AuthorAdmin) 13 | admin.site.register(Machine, AuthorAdmin) 14 | admin.site.register(Space, AuthorAdmin) 15 | admin.site.register(Consensus, AuthorAdmin) 16 | -------------------------------------------------------------------------------- /_database/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class DatabaseConfig(AppConfig): 5 | name = '_database' 6 | -------------------------------------------------------------------------------- /_database/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_database/management/__init__.py -------------------------------------------------------------------------------- /_database/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_database/management/commands/__init__.py -------------------------------------------------------------------------------- /_database/management/commands/announce_events.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from _database.models import Event 3 | 4 | 5 | class Command(BaseCommand): 6 | help = "Announce upcoming events (Noisebridge specific)" 7 | 8 | def handle(self, *args, **options): 9 | Event.objects.QUERYSET__upcoming().announce() 10 | -------------------------------------------------------------------------------- /_database/management/commands/publish_events.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from _database.models import Event 3 | from pyprintplus import Log 4 | 5 | 6 | class Command(BaseCommand): 7 | help = "Publish new events after 24hour" 8 | 9 | def handle(self, *args, **options): 10 | Log().print('publish_events.py') 11 | Event.objects.QUERYSET__not_approved().QUERYSET__older_then_24h().publish() 12 | -------------------------------------------------------------------------------- /_database/migrations/0002_event_boolean_online_meetup.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.4 on 2020-03-28 13:37 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('_database', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='event', 15 | name='boolean_online_meetup', 16 | field=models.BooleanField(default=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /_database/migrations/0003_auto_20200330_1452.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.4 on 2020-03-30 14:52 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('_database', '0002_event_boolean_online_meetup'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='event', 15 | name='float_lat', 16 | field=models.FloatField(blank=True, default=37.762389, null=True, verbose_name='Lat'), 17 | ), 18 | migrations.AlterField( 19 | model_name='event', 20 | name='float_lon', 21 | field=models.FloatField(blank=True, default=-122.4191587, null=True, verbose_name='Lon'), 22 | ), 23 | migrations.AlterField( 24 | model_name='event', 25 | name='str_location', 26 | field=models.CharField(blank=True, default='Noisebridge
2169 Mission St 0) 27 | 28 | def test_JSON__overlapping_events(self): 29 | # get event and then see if it shows up as overlapping 30 | event = Event.objects.QUERYSET__upcoming()[0] 31 | self.assertTrue(len(Event.objects.JSON__overlapping_events( 32 | event.int_UNIXtime_event_start, 120, 'Hackatorium')['overlapping_events']) > 0) 33 | 34 | def test_QUERYSET__in_space(self): 35 | event = Event.objects.QUERYSET__upcoming()[0] 36 | event.one_space = Space.objects.all()[0] 37 | event.save() 38 | self.assertTrue( 39 | len(Event.objects.QUERYSET__in_space(one_space=event.one_space)) > 0) 40 | 41 | def test_LIST__in_minutes(self): 42 | self.assertTrue(type(Event.objects.LIST__in_minutes(10)) == list) 43 | 44 | def test_LIST__search_results(self): 45 | self.assertTrue( 46 | type(Event.objects.all().LIST__search_results()) == list) 47 | -------------------------------------------------------------------------------- /_database/tests/test_guildes.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _database.models import Guilde 3 | 4 | 5 | class GuildesTestCase(TestCase): 6 | @classmethod 7 | def setUpTestData(cls): 8 | Guilde(str_name_en_US='Laser Guilde').save() 9 | 10 | def test_LIST__search_results(self): 11 | self.assertTrue(len(Guilde.objects.LIST__search_results()) > 0) 12 | -------------------------------------------------------------------------------- /_database/tests/test_machines.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _database.models import Machine 3 | 4 | 5 | class MachinesTestCase(TestCase): 6 | @classmethod 7 | def setUpTestData(cls): 8 | Machine(str_name_en_US='Laser Cutter').save() 9 | 10 | def test_LIST__search_results(self): 11 | self.assertTrue(len(Machine.objects.LIST__search_results()) > 0) 12 | -------------------------------------------------------------------------------- /_database/tests/test_meetingnotes.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _database.models import MeetingNote 3 | 4 | 5 | class MeetingNotesTestCase(TestCase): 6 | def test_LIST__search_results(self): 7 | MeetingNote.objects.import_all_from_wiki( 8 | WIKI_API_URL='https://www.noisebridge.net/api.php', test=True) 9 | self.assertTrue(len(MeetingNote.objects.LIST__search_results()) > 0) 10 | 11 | def test_start_and_meeting_end(self): 12 | MeetingNote().start('hackspace-os-test') 13 | MeetingNote().end('hackspace-os-test') 14 | -------------------------------------------------------------------------------- /_database/tests/test_persons.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _database.models import Person 3 | 4 | 5 | class PersonsTestCase(TestCase): 6 | @classmethod 7 | def setUpTestData(cls): 8 | Person.objects.import_from_discourse( 9 | DISCOURSE_URL='https://discuss.noisebridge.info') 10 | 11 | def test_import_from_discourse(self): 12 | self.assertTrue(Person.objects.count() > 0) 13 | -------------------------------------------------------------------------------- /_database/tests/test_photos.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | from _database.models import Photo 4 | 5 | 6 | class PhotosTestCase(TestCase): 7 | def test_import_from_google_photos(self): 8 | Photo.objects.import_from_google_photos(test=True) 9 | 10 | def test_import_from_twitter(self): 11 | Photo.objects.import_from_twitter(test=True) 12 | 13 | def test_import_from_wiki(self): 14 | Photo.objects.import_from_wiki(test=True) 15 | 16 | def test_import_from_flickr(self): 17 | Photo.objects.import_from_flickr(test=True) 18 | 19 | def test_import_from_instagram(self): 20 | Photo.objects.import_from_instagram(test=True) 21 | 22 | def test_count_overview(self): 23 | self.assertTrue(type(Photo.objects.count_overview()) == dict) 24 | 25 | def test_random(self): 26 | self.assertTrue(type(Photo.objects.random()) == list) 27 | -------------------------------------------------------------------------------- /_database/tests/test_projects.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _database.models import Project 3 | 4 | 5 | class ProjectsTestCase(TestCase): 6 | @classmethod 7 | def setUpTestData(cls): 8 | Project.objects.import_from_discourse( 9 | DISCOURSE_URL='https://discuss.noisebridge.info') 10 | 11 | def test_LIST__search_results(self): 12 | self.assertTrue(len(Project.objects.LIST__search_results()) > 0) 13 | -------------------------------------------------------------------------------- /_database/tests/test_spaces.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _database.models import Space 3 | 4 | 5 | class SpacesTestCase(TestCase): 6 | @classmethod 7 | def setUpTestData(cls): 8 | Space(str_name_en_US='Hackatorium').save() 9 | Space(str_name_en_US='Turing Room').save() 10 | 11 | def test_LIST__search_results(self): 12 | self.assertTrue(len(Space.objects.LIST__search_results()) > 0) 13 | -------------------------------------------------------------------------------- /_database/tests/test_wishes.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _database.models import Wish 3 | 4 | 5 | class WishesTestCase(TestCase): 6 | @classmethod 7 | def setUpTestData(cls): 8 | Wish(str_name_en_US='I wish people would clean up after themself.').save() 9 | Wish(str_name_en_US='I wish we would have a high end gaming pc.').save() 10 | 11 | def test_LIST__search_results(self): 12 | self.assertTrue(len(Wish.objects.LIST__search_results()) > 0) 13 | -------------------------------------------------------------------------------- /_database/urls.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_database/urls.py -------------------------------------------------------------------------------- /_readme_images/headerimage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/headerimage.jpg -------------------------------------------------------------------------------- /_readme_images/heading_about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_about.png -------------------------------------------------------------------------------- /_readme_images/heading_consensus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_consensus.png -------------------------------------------------------------------------------- /_readme_images/heading_contribute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_contribute.png -------------------------------------------------------------------------------- /_readme_images/heading_customize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_customize.png -------------------------------------------------------------------------------- /_readme_images/heading_donate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_donate.png -------------------------------------------------------------------------------- /_readme_images/heading_events.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_events.png -------------------------------------------------------------------------------- /_readme_images/heading_examples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_examples.png -------------------------------------------------------------------------------- /_readme_images/heading_features.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_features.png -------------------------------------------------------------------------------- /_readme_images/heading_landingpage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_landingpage.png -------------------------------------------------------------------------------- /_readme_images/heading_led_darkmode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_led_darkmode.png -------------------------------------------------------------------------------- /_readme_images/heading_meeting_notes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_meeting_notes.png -------------------------------------------------------------------------------- /_readme_images/heading_multi_language.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_multi_language.png -------------------------------------------------------------------------------- /_readme_images/heading_photos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_photos.png -------------------------------------------------------------------------------- /_readme_images/heading_projects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_projects.png -------------------------------------------------------------------------------- /_readme_images/heading_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_search.png -------------------------------------------------------------------------------- /_readme_images/heading_setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_setup.png -------------------------------------------------------------------------------- /_readme_images/heading_spaces.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_spaces.png -------------------------------------------------------------------------------- /_readme_images/heading_template_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/heading_template_name.png -------------------------------------------------------------------------------- /_readme_images/screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_1.png -------------------------------------------------------------------------------- /_readme_images/screenshot_about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_about.png -------------------------------------------------------------------------------- /_readme_images/screenshot_consensus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_consensus.png -------------------------------------------------------------------------------- /_readme_images/screenshot_donate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_donate.png -------------------------------------------------------------------------------- /_readme_images/screenshot_events.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_events.png -------------------------------------------------------------------------------- /_readme_images/screenshot_landingpage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_landingpage.png -------------------------------------------------------------------------------- /_readme_images/screenshot_led_dark_mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_led_dark_mode.png -------------------------------------------------------------------------------- /_readme_images/screenshot_meeting_notes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_meeting_notes.png -------------------------------------------------------------------------------- /_readme_images/screenshot_multi_language.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_multi_language.png -------------------------------------------------------------------------------- /_readme_images/screenshot_photos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_photos.png -------------------------------------------------------------------------------- /_readme_images/screenshot_projects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_projects.png -------------------------------------------------------------------------------- /_readme_images/screenshot_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_search.png -------------------------------------------------------------------------------- /_readme_images/screenshot_spaces_machines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_readme_images/screenshot_spaces_machines.png -------------------------------------------------------------------------------- /_setup/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_setup/__init__.py -------------------------------------------------------------------------------- /_setup/cronjobs.txt: -------------------------------------------------------------------------------- 1 | */30 * * * * python manage.py publish_events 2 | */10 * * * * python manage.py update_database -------------------------------------------------------------------------------- /_setup/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_setup/management/__init__.py -------------------------------------------------------------------------------- /_setup/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_setup/management/commands/__init__.py -------------------------------------------------------------------------------- /_setup/management/commands/setup.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from _setup.models import Setup 3 | 4 | 5 | class Command(BaseCommand): 6 | help = "start the setup" 7 | 8 | def handle(self, *args, **options): 9 | Setup()._menu() 10 | -------------------------------------------------------------------------------- /_setup/meeting_notes_template.txt: -------------------------------------------------------------------------------- 1 | These are the notes from the {{ MeetingNumber }}th Meeting of {{ HackspaceName }}. 2 | 3 | Date: {{ Date }} 4 | Note-taker: '''NOTE TAKER NAME''' 5 | Moderators: '''MODERATOR TAKER NAME''' 6 | 7 | == Meeting Summary == 8 | '''FILL OUT AT END OF MEETING - One or two bullet points of high-level meeting summary.''' 9 | What happened at the meeting: 10 | * Announcements: 11 | * Finances: 12 | * Consensus Items: 13 | * Discussion Items: 14 | 15 | = Introductions = 16 | '''PREFERRED PRONONON & NAME, 1-2 SENTENCES OF WHAT YOU DO/ARE INTERESTED IN''' 17 | 18 | 19 | = Short announcements and events = 20 | '''60-second description per item in bulletpoint.''' 21 | 22 | 23 | = Excellence = 24 | '''Our One Rule is to Be Excellent to Each Other.''' 25 | 26 | (What does that mean? How does the Anti-Harassment Policy fit into this? Are we SURE we know what being Excellent is? Also let's talk about Security in the space? This is an important and fundamental conversation at 27 | , so let's give it like 120 seconds.) 28 | 29 | 30 | = Participation = 31 | '''Everyone at {{ HackspaceName }} is a participant at {{ HackspaceName }}.''' 32 | 33 | (What does that mean? How do you get a door key? Access to Telegram, Discourse?) 34 | 35 | = Financial Report = 36 | '''Anarchist societies under a capitalist state need money to survive and thrive, yo.''' 37 | 38 | * Funds in bank: 39 | * Any other details by those participating in handling our financials 40 | * The latest financial reports from the treasurer 41 | 42 | 43 | = Consensus = 44 | '''Consensus is how the {{ HackspaceName }} Membership may change how {{ HackspaceName }} works.''' 45 | 46 | (How does Consensus work? What types of things are good for formal Consensus? What is small-c consensus? What is a "block"?) 47 | 48 | == [[ Consensus Items History | Proposals from last week ]] == 49 | ''(Add any items which are consensed upon or someone has raised a principle objection for to the [[Consensus Items History]] page.)'' 50 | 51 | == [[ Current Consensus Items | Proposals for next week ]] == 52 | ''(Add any new items for consensus to the [[Current Consensus Items]] page.)'' 53 | 54 | 55 | 56 | 57 | = Discussion = 58 | 59 | == Discussion Item 1 == 60 | 61 | == Discussion Item 2 == 62 | 63 | = End of Meeting = 64 | -------------------------------------------------------------------------------- /_setup/models/__init__.py: -------------------------------------------------------------------------------- 1 | from _setup.models.config import Config 2 | from _setup.models.cronjobs import Cronjob 3 | from _setup.models.secrets import Secret 4 | from _setup.models.setup import Setup 5 | from _setup.models.startup import Startup 6 | -------------------------------------------------------------------------------- /_setup/models/config.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | import time 4 | 5 | 6 | class Config(): 7 | def __init__(self, target=None, username_for=None, file_path='_setup/config.json', show_log=True): 8 | self.logs = ['self.__init__'] 9 | self.started = round(time.time()) 10 | self.show_log = show_log 11 | self.file_path = file_path 12 | 13 | try: 14 | with open(file_path) as json_file: 15 | self.value = json.load(json_file) 16 | 17 | if target: 18 | path = target.split('.') 19 | for part in path: 20 | self.value = self.value[part] 21 | 22 | if username_for: 23 | if username_for.endswith('/'): 24 | username_for = username_for[:-1] 25 | # check if instagram is saved in social channels 26 | for entry in self.value: 27 | if username_for+'/' in entry['url']: 28 | self.value = entry['url'].split( 29 | username_for+'/')[1].replace('/', '') 30 | break 31 | else: 32 | self.value = None 33 | except KeyError: 34 | # if field doesn't exist, add it to config.json 35 | self.value = None 36 | 37 | def log(self, text): 38 | from pyprintplus import Log 39 | self.logs.append(text) 40 | if self.show_log == True: 41 | Log().print('{}'.format(text), os.path.basename(__file__), self.started) 42 | -------------------------------------------------------------------------------- /_setup/models/setup.py: -------------------------------------------------------------------------------- 1 | class Setup(): 2 | def __init__(self, test=False): 3 | self.test = test 4 | self.backup_files = [ 5 | 'db.sqlite3', 6 | '_setup/config.json', 7 | '_setup/secrets.json', 8 | '_website/static/images/logo.svg', 9 | '_website/static/images/header_logo.jpg', 10 | '_website/static/images/header_banner.jpg', 11 | '_website/static/images/favicons/favicon.ico', 12 | '_website/static/images/favicons/favicon-32x32.png', 13 | '_website/static/images/favicons/favicon-16x16.png', 14 | '_website/static/images/favicons/apple-touch-icon.png', 15 | ] 16 | 17 | @property 18 | def complete(self): 19 | import os 20 | # check if config and secrets file exist 21 | if os.path.isfile('_setup/config.json') and os.path.isfile('_setup/secrets.json'): 22 | return True 23 | else: 24 | return False 25 | 26 | @property 27 | def database_exists(self): 28 | import os 29 | # check if config and secrets file exist 30 | if os.path.isfile('db.sqlite3'): 31 | return True 32 | else: 33 | return False 34 | 35 | def _menu(self): 36 | from _setup.models.setup_functions.menu import SetupMenu 37 | SetupMenu(self.backup_files, self.test) 38 | 39 | def _new(self): 40 | from _setup.models.setup_functions.new import SetupNew 41 | SetupNew(self.test) 42 | 43 | def _export(self): 44 | from _setup.models.setup_functions.export import SetupExport 45 | SetupExport(self.backup_files, self.test) 46 | 47 | def _import(self): 48 | from _setup.models.setup_functions.import_setup import SetupImport 49 | SetupImport(self.backup_files, self.test) 50 | 51 | def _delete(self): 52 | from _setup.models.setup_functions.delete import SetupDelete 53 | SetupDelete(self.backup_files, self.test) 54 | -------------------------------------------------------------------------------- /_setup/models/setup_functions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_setup/models/setup_functions/__init__.py -------------------------------------------------------------------------------- /_setup/models/setup_functions/delete.py: -------------------------------------------------------------------------------- 1 | from pyprintplus import Log 2 | import os 3 | 4 | 5 | class SetupDelete(): 6 | def __init__(self, backup_files, test=False): 7 | self.backup_files = backup_files 8 | self.test = test 9 | 10 | Log().show_message( 11 | 'WARNING: Are you sure you want to delete your current setup? This will delete the config.json, secrets.json and your logos & favicons. Enter "delete" to delete the current setup.') 12 | confirm = 'delete' if self.test else input() 13 | if confirm == 'delete': 14 | for file_path in self.backup_files: 15 | if os.path.exists(file_path): 16 | os.remove(file_path) 17 | 18 | Log().show_message('✅Done! I deleted the current setup.') 19 | 20 | else: 21 | Log().show_message('Ok. I won\'t delete anything.') 22 | -------------------------------------------------------------------------------- /_setup/models/setup_functions/export.py: -------------------------------------------------------------------------------- 1 | from pyprintplus import Log 2 | 3 | 4 | class SetupExport(): 5 | def __init__(self, backup_files, test=False): 6 | self.backup_files = backup_files 7 | self.test = test 8 | 9 | Log().show_messages([ 10 | 'Hello! It seems you want to export your current settings? (your config.json, secrets.json and important images)' 11 | ]) 12 | 13 | Log().show_message( 14 | 'If that\'s the case, enter now a name for the exported folder. (or press Enter to exit)') 15 | 16 | folder_name = 'unittest' if self.test else input() 17 | 18 | if not folder_name: 19 | Log().show_message('Ok, got it. Maybe another time.') 20 | exit() 21 | else: 22 | from zipfile import ZipFile, ZIP_DEFLATED 23 | 24 | # copy files into folder 25 | with ZipFile('setup_backup__'+folder_name+'.zip', 'w', ZIP_DEFLATED) as zip: 26 | # writing each file one by one 27 | for file in self.backup_files: 28 | try: 29 | zip.write(file) 30 | except: 31 | pass 32 | 33 | Log().show_message('✅Done! Exported "'+folder_name + 34 | '" ('+self.get_size('setup_backup__'+folder_name+'.zip')+')') 35 | 36 | def get_size(self, file_path): 37 | import os 38 | return str(round(os.path.getsize(file_path)/1000000, 1))+' MB' 39 | -------------------------------------------------------------------------------- /_setup/models/setup_functions/new_functions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_setup/models/setup_functions/new_functions/__init__.py -------------------------------------------------------------------------------- /_setup/models/setup_functions/new_functions/event_footer.py: -------------------------------------------------------------------------------- 1 | class SetupNewEventFooter(): 2 | def __init__(self, config): 3 | self.config = config 4 | 5 | # auto generate the event footer for discourse and meetup 6 | if self.config['WEBSITE']['DOMAIN'] and self.config['BASICS']['NAME']: 7 | self.config['EVENTS']['DISCOURSE_AND_MEETUP_EVENT_FOOTER_HTML'] =\ 8 | '
------------------
'\ 9 | '
'+self.config['BASICS']['NAME']+' is funded by YOUR donations. '\ 10 | 'So if you want to support '+self.config['BASICS']['NAME']+' - donations are always welcomed - '\ 11 | 'money, hardware or time (by organizing or volunteering an event). '\ 12 | 'Visit https://' + \ 13 | self.config['WEBSITE']['DOMAIN']+' for more details.' 14 | -------------------------------------------------------------------------------- /_setup/models/setup_functions/new_functions/languages.py: -------------------------------------------------------------------------------- 1 | from pyprintplus import Log 2 | 3 | 4 | class SetupLanguages(): 5 | def __init__(self, config, test=False): 6 | self.config = config 7 | self.test = test 8 | 9 | Log().show_message( 10 | 'Besides english - what languages should your website support? Currently available: hebrew.') 11 | input_languages = ['hebrew'] if self.test else input().replace( 12 | ', ', ',').split(',') 13 | self.config['WEBSITE']['LANGUAGES'] = ['english'] 14 | if 'hebrew' in input_languages: 15 | self.config['WEBSITE']['LANGUAGES'].append('hebrew') 16 | else: 17 | # remove hebrew text options 18 | for element in self.config['BASICS']['HACKERSPACE_IS_SENTENCES']: 19 | element.pop('hebrew', None) 20 | for element in self.config['PHYSICAL_SPACE']['ADDRESS']: 21 | element.pop('HOW_TO_FIND_US__hebrew', None) 22 | -------------------------------------------------------------------------------- /_setup/models/setup_functions/new_functions/riseuppad.py: -------------------------------------------------------------------------------- 1 | from pyprintplus import Log 2 | 3 | 4 | class SetupNewRiseupPad(): 5 | def __init__(self, config): 6 | self.config = config 7 | 8 | if self.config['BASICS']['NAME']: 9 | Log().show_message( 10 | 'Ok, great! Give me a seconds, so I can try to setup your RISEUPPAD_MEETING_PATH, and MEETUP_GROUP as well...') 11 | 12 | # if hackspace name saved, also save other config defaults based on name 13 | self.config['MEETINGS']['RISEUPPAD_MEETING_PATH'] = self.config['BASICS']['NAME'].lower() + \ 14 | '-meetings' 15 | -------------------------------------------------------------------------------- /_setup/secrets_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "DJANGO": { 3 | "SECRET_KEY": null, 4 | "ADMIN_URL": null, 5 | "ADMIN_USER": { 6 | "USERNAME": null, 7 | "PASSWORD": null 8 | } 9 | }, 10 | "AWS": { 11 | "ACCESS_KEYID": null, 12 | "SECRET_ACCESS_KEY": null, 13 | "S3": { 14 | "BUCKET_NAME": null, 15 | "SERVER_AREA": null 16 | } 17 | }, 18 | "DISCOURSE": { 19 | "DISCOURSE_URL": null, 20 | "API_KEY": null, 21 | "API_USERNAME": null 22 | }, 23 | "MEETUP": { 24 | "ACCESS_TOKEN": null, 25 | "ACCESS_TOKEN_VALID_UPTO": null, 26 | "EMAIL": null, 27 | "PASSWORD": null, 28 | "REDIRECT_URI": null, 29 | "CLIENT_ID": null, 30 | "CLIENT_SECRET": null 31 | }, 32 | "SLACK": { 33 | "API_TOKEN": null 34 | }, 35 | "TELEGRAM": { 36 | "BOT_TOKEN": null, 37 | "GROUP_CHATID": null 38 | }, 39 | "GOOGLE_PHOTOS": { 40 | "CLIENT_ID": null, 41 | "CLIENT_SECRET": null 42 | }, 43 | "REMOTE_WEBDRIVER_IP": null 44 | } -------------------------------------------------------------------------------- /_setup/tests/test_new_setup.json: -------------------------------------------------------------------------------- 1 | { 2 | "BASICS": { 3 | "NAME": "TAMI", 4 | "WIKI": { 5 | "API_URL": "https://wiki.telavivmakers.org/api.php", 6 | "PHOTOS_IGNORE_PAGES": [] 7 | }, 8 | "DONATION_URLs": { 9 | "MONEY": "https://telavivmakers.org/donate", 10 | "HARDWARE": null 11 | }, 12 | "EMBEDDED_MAP_URL": "https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d54085.416809235605!2d34.7561820332218!3d32.087134583396185!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x151d4ca3c50d1ee7%3A0xd083e66d34f22859!2sTAMI%20hackspace!5e0!3m2!1sen!2sro!4v1575741469803!5m2!1sen!2sro" 13 | }, 14 | "WEBSITE": { 15 | "DOMAIN": "telavivmakers.org", 16 | "LANGUAGES": [ 17 | "english", 18 | "hebrew" 19 | ] 20 | }, 21 | "CSS": { 22 | "PRIMARY_COLOR": "#9300a0" 23 | }, 24 | "EVENTS": { 25 | "MEETUP_GROUP": "https://meetup.com/Tel-Aviv-Makers-TAMI" 26 | }, 27 | "CONTACT": { 28 | "TELEGRAM_GROUPS": [{ 29 | "NAME": "TAMI", 30 | "INVITE_URL": "https://bit.ly/tami-main" 31 | }, 32 | { 33 | "NAME": "Is Somebody At TAMI", 34 | "INVITE_URL": "https://t.me/ISATAMI/" 35 | } 36 | ] 37 | }, 38 | "PHYSICAL_SPACE": { 39 | "ADDRESS": { 40 | "STREET": "Kibbutz Galuyot 45", 41 | "ZIP": "6655031", 42 | "CITY": "Tel Aviv", 43 | "STATE": "Tel Aviv-Yafo", 44 | "COUNTRYCODE": "IL", 45 | "HOW_TO_FIND_US__english": "3rd floor" 46 | } 47 | }, 48 | "SOCIAL": { 49 | "GOOGLE_PHOTOS_ALBUM_URLS": [ 50 | "https://photos.google.com/share/AF1QipNdUmxDzWRLtsxIcWIugAjr5gN_GBPd18XpfSkeSWteXPwqJC-c5_HTYjy-dQJPXQ?key=WVA4ekpWZE1HMlNvdzdSVkJGLS1yZTZaQ1Q3bW13" 51 | ], 52 | "HASHTAG": "TAMIhackerspace", 53 | "DISCOURSE_GROUP": "https://discourse.telavivmakers.org/", 54 | "INSTAGRAM_USERNAME": null, 55 | "TWITTER_USERNAME": null 56 | } 57 | } -------------------------------------------------------------------------------- /_setup/tests/test_setup.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from _setup.models import Setup 3 | import json 4 | import os 5 | 6 | 7 | class SetupTestConfig(): 8 | def __init__(self, target): 9 | with open('_setup/tests/test_new_setup.json') as json_file: 10 | self.value = json.load(json_file) 11 | 12 | if target: 13 | path = target.split('.') 14 | for part in path: 15 | self.value = self.value[part] 16 | 17 | 18 | class SetupTestCase(TestCase): 19 | @classmethod 20 | def setUpClass(cls): 21 | super().setUpClass() 22 | # rename config file to temp backup 23 | if os.path.isfile('_setup/config.json'): 24 | os.rename('_setup/config.json', '_setup/config_temp_backup.json') 25 | if os.path.isfile('_setup/secrets.json'): 26 | os.rename('_setup/secrets.json', '_setup/secrets_temp_backup.json') 27 | 28 | @classmethod 29 | def tearDownClass(cls): 30 | # delete new files and rename temp backup back to normal 31 | if os.path.isfile('_setup/config.json'): 32 | os.remove('_setup/config.json') 33 | if os.path.isfile('_setup/secrets.json'): 34 | os.remove('_setup/secrets.json') 35 | if os.path.isfile('setup_backup__unittest.zip'): 36 | os.remove('setup_backup__unittest.zip') 37 | 38 | if os.path.isfile('_setup/config_temp_backup.json'): 39 | os.rename('_setup/config_temp_backup.json', '_setup/config.json') 40 | if os.path.isfile('_setup/secrets_temp_backup.json'): 41 | os.rename('_setup/secrets_temp_backup.json', '_setup/secrets.json') 42 | 43 | super().tearDownClass() 44 | 45 | def test_menu(self): 46 | Setup(test=True)._menu() 47 | 48 | def test_new_export_delete_import(self): 49 | setup = Setup(test=True) 50 | 51 | # create a new setup 52 | setup._new() 53 | 54 | # then export that new setup 55 | setup._export() 56 | 57 | # then delete the new setup 58 | setup._delete() 59 | 60 | # then import the new setup 61 | setup._import() 62 | -------------------------------------------------------------------------------- /_translations/donate.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% block content %} 3 | 4 | 5 | {% if word == 'SPACE is funded by donations. ...' %} 6 | {% if language == 'hebrew' %} 7 | {{ 'BASICS.NAME'|get_config }} 8 | ממומן על ידי התרומות של כולנו.
9 | אז בבקשה עזרו לנו לשמור על 10 | {{ 'BASICS.NAME'|get_config }} 11 | בחיים וצומח! בכסף, בחומרה או בזמן! 12 | {% else %} 13 | {{ 'BASICS.NAME'|get_config }} is funded by YOUR donations.
14 | So please help us keeping {{ 'BASICS.NAME'|get_config }} alive & growing! With money, hardware or your time! 15 | {% endif %} 16 | 17 | 18 | {% elif word == 'Donations are tax deductible.' %} 19 | {% if language == 'hebrew' %} 20 | התרומות ניתנות לניכוי מס. 21 | {% else %} 22 | Donations are tax deductible. 23 | {% endif %} 24 | 25 | 26 | {% elif word == 'Donate money' %} 27 | {% if language == 'hebrew' %} 28 | תרומת 29 |
30 | כסף 31 | {% else %} 32 | Donate
33 | money 34 | {% endif %} 35 | 36 | 37 | {% elif word == 'Donate hardware' %} 38 | {% if language == 'hebrew' %} 39 | תרומת 40 |
41 | חומרה 42 | {% else %} 43 | Donate
44 | hardware 45 | {% endif %} 46 | 47 | 48 | {% elif word == 'Organize an event' %} 49 | {% if language == 'hebrew' %} 50 | ארגון 51 |
52 | אירוע 53 | {% else %} 54 | Organize
55 | an event 56 | {% endif %} 57 | 58 | 59 | {% elif word == 'Volunteer at an event' %} 60 | {% if language == 'hebrew' %} 61 | התנדבות 62 |
63 | באירוע 64 | {% else %} 65 | Volunteer
66 | at an event 67 | {% endif %} 68 | 69 | 70 | {% elif word == 'Become a Patreon' %} 71 | {% if language == 'hebrew' %} 72 | להיות
פטריון 73 | {% else %} 74 | Become
a Patreon 75 | {% endif %} 76 | 77 | 78 | {% else %} 79 | {{ word }} 80 | 81 | {% endif %} 82 | {% endblock%} -------------------------------------------------------------------------------- /_translations/languages.json: -------------------------------------------------------------------------------- 1 | { 2 | "english": "en", 3 | "hebrew": "iw", 4 | "german": "de" 5 | } -------------------------------------------------------------------------------- /_translations/menu.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | 3 | {% if word == 'Landingpage' %} 4 | {% if language == 'hebrew' %} 5 | דף נחיתה 6 | {% else %} 7 | Landingpage 8 | {% endif %} 9 | 10 | 11 | {% elif word == 'About' %} 12 | {% if language == 'hebrew' %} 13 | אודות 14 | {% else %} 15 | About 16 | {% endif %} 17 | 18 | 19 | {% elif word == 'Values' %} 20 | {% if language == 'hebrew' %} 21 | ערכים 22 | {% else %} 23 | Values 24 | {% endif %} 25 | 26 | 27 | {% elif word == 'Photos' %} 28 | {% if language == 'hebrew' %} 29 | תמונות 30 | {% else %} 31 | Photos 32 | {% endif %} 33 | 34 | 35 | {% elif word == 'Participate' %} 36 | {% if language == 'hebrew' %} 37 | השתתפות 38 | {% else %} 39 | Participate 40 | {% endif %} 41 | 42 | 43 | {% elif word == 'Events' %} 44 | {% if language == 'hebrew' %} 45 | אירועים 46 | {% else %} 47 | Events 48 | {% endif %} 49 | 50 | 51 | {% elif word == 'Discussions' %} 52 | {% if language == 'hebrew' %} 53 | דיונים 54 | {% else %} 55 | Discussions 56 | {% endif %} 57 | 58 | 59 | {% elif word == 'Projects' %} 60 | {% if language == 'hebrew' %} 61 | פרויקטים 62 | {% else %} 63 | Projects 64 | {% endif %} 65 | 66 | 67 | {% elif word == 'Spaces' %} 68 | {% if language == 'hebrew' %} 69 | מרחבים 70 | {% else %} 71 | Spaces 72 | {% endif %} 73 | 74 | 75 | {% elif word == 'Machines' %} 76 | {% if language == 'hebrew' %} 77 | מכונות 78 | {% else %} 79 | Machines 80 | {% endif %} 81 | 82 | 83 | {% elif word == 'Meetings' %} 84 | {% if language == 'hebrew' %} 85 | מפגשים 86 | {% else %} 87 | Meetings 88 | {% endif %} 89 | 90 | 91 | {% elif word == 'Consensus' %} 92 | {% if language == 'hebrew' %} 93 | הסכמות 94 | {% else %} 95 | Consensus 96 | {% endif %} 97 | 98 | 99 | {% elif word == 'Guildes' %} 100 | {% if language == 'hebrew' %} 101 | גילדות 102 | {% else %} 103 | Guildes 104 | {% endif %} 105 | 106 | 107 | {% elif word == 'Search ...' %} 108 | {% if language == 'hebrew' %} 109 | חיפוש ... 110 | {% else %} 111 | Search ... 112 | {% endif %} 113 | 114 | 115 | {% elif word == 'Searching ...' %} 116 | {% if language == 'hebrew' %} 117 | מחפש ... 118 | {% else %} 119 | Searching ... 120 | {% endif %} 121 | 122 | 123 | {% else %} 124 | {{ word }} 125 | 126 | {% endif %} 127 | {% endblock%} -------------------------------------------------------------------------------- /_translations/photos.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | 3 | {% if word == 'Latest' %} 4 | {% if language == 'hebrew' %} 5 | החדש ביותר 6 | {% else %} 7 | Latest 8 | {% endif %} 9 | 10 | 11 | {% elif word == 'Oldest' %} 12 | {% if language == 'hebrew' %} 13 | הישן ביותר 14 | {% else %} 15 | Oldest 16 | {% endif %} 17 | 18 | 19 | {% elif word == 'Random' %} 20 | {% if language == 'hebrew' %} 21 | אקראי 22 | {% else %} 23 | Random 24 | {% endif %} 25 | 26 | 27 | {% elif word == 'Want to see your photos here?' %} 28 | {% if language == 'hebrew' %} 29 | רוצה לראות את התמונות שלך כאן? 30 | {% else %} 31 | Want to see your photos here? 32 | {% endif %} 33 | 34 | 35 | {% elif word == 'Use' %} 36 | {% if language == 'hebrew' %} 37 | להשתמש 38 | {% else %} 39 | Use 40 | {% endif %} 41 | 42 | 43 | {% else %} 44 | {{ word }} 45 | 46 | {% endif %} 47 | {% endblock%} -------------------------------------------------------------------------------- /_website/__init__.py: -------------------------------------------------------------------------------- 1 | default_app_config = '_website.apps.WebsiteConfig' 2 | -------------------------------------------------------------------------------- /_website/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | -------------------------------------------------------------------------------- /_website/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class WebsiteConfig(AppConfig): 5 | name = '_website' 6 | -------------------------------------------------------------------------------- /_website/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/management/__init__.py -------------------------------------------------------------------------------- /_website/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/management/commands/__init__.py -------------------------------------------------------------------------------- /_website/models/__init__.py: -------------------------------------------------------------------------------- 1 | from _website.models.request import Request 2 | from _website.models.response import Response 3 | -------------------------------------------------------------------------------- /_website/models/request.py: -------------------------------------------------------------------------------- 1 | import time 2 | from pyprintplus import Log 3 | 4 | 5 | class Request(): 6 | def __init__(self, request=None, show_log=True): 7 | self.logs = ['self.__init__'] 8 | self.started = round(time.time()) 9 | self.show_log = show_log 10 | self.request = request 11 | self.url = request.build_absolute_uri() if request else None 12 | self.hash = self.url.split( 13 | '#')[1] if self.url and '#' in self.url else None 14 | self.user = request.user if request else None 15 | self.search = request.GET.get('search', None) if request else None 16 | 17 | if request and request.GET.get('lang', None): 18 | self.language = request.GET.get('lang', None) 19 | elif request and request.COOKIES.get('lang', None): 20 | self.language = request.COOKIES.get('lang', None) 21 | else: 22 | self.language = 'english' 23 | 24 | self.in_space = True if request and (request.COOKIES.get( 25 | 'in_space') or request.GET.get('in_space', None) == 'True') else False 26 | 27 | def log(self, text): 28 | import os 29 | self.logs.append(text) 30 | if self.show_log == True: 31 | Log().print('{}'.format(text), os.path.basename(__file__), self.started) 32 | -------------------------------------------------------------------------------- /_website/models/response.py: -------------------------------------------------------------------------------- 1 | from pyprintplus import Log 2 | import time 3 | import re 4 | TAG_RE = re.compile(r'<[^>]+>') 5 | 6 | 7 | class Response(): 8 | def __init__(self, show_log=True): 9 | self.logs = ['self.__init__'] 10 | self.started = round(time.time()) 11 | self.show_log = show_log 12 | 13 | def log(self, text): 14 | import os 15 | self.logs.append(text) 16 | if self.show_log == True: 17 | Log().print('{}'.format(text), os.path.basename(__file__), self.started) 18 | 19 | @property 20 | def description(self): 21 | from _setup.models import Config 22 | NAME = Config('BASICS.NAME').value 23 | HACKERSPACE_IS_SENTENCES = Config( 24 | 'BASICS.HACKERSPACE_IS_SENTENCES').value 25 | return NAME + ' '+TAG_RE.sub('', HACKERSPACE_IS_SENTENCES['english'][0])+('.' if not TAG_RE.sub('', HACKERSPACE_IS_SENTENCES['english'][0]).endswith('.') else '') 26 | -------------------------------------------------------------------------------- /_website/static/css/consensus.css: -------------------------------------------------------------------------------- 1 | .block__consensus_item_preview { 2 | background-color: white; 3 | display: block; 4 | padding: 15px; 5 | border-radius: 15px; 6 | text-decoration: none; 7 | color: black; 8 | margin-bottom: 20px; 9 | margin-top: 20px; 10 | padding-left: 20px; 11 | padding-right: 20px; 12 | -webkit-transition: all 200ms ease; 13 | transition: all 200ms ease; 14 | box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.25); 15 | } 16 | 17 | .block__consensus_item_preview:hover { 18 | box-shadow: 0 7px 6px 0 rgba(0, 0, 0, 0.25); 19 | -webkit-transform: translate(0px, -5px); 20 | -ms-transform: translate(0px, -5px); 21 | transform: translate(0px, -5px); 22 | } 23 | 24 | @media (prefers-color-scheme: dark) { 25 | .block__consensus_item_preview { 26 | color: #d4d4d4; 27 | background-color: black; 28 | -webkit-animation: LEDsStrong 8s infinite; 29 | /* Safari 4.0 - 8.0 */ 30 | animation: LEDsStrong 8s infinite; 31 | } 32 | } 33 | 34 | 35 | .consensus_item_by { 36 | display: inline-block; 37 | color: #979797; 38 | margin-bottom: 10px; 39 | margin-left: 5px; 40 | } 41 | 42 | .consensus_item_by__image { 43 | background-size: contain; 44 | background-repeat: no-repeat; 45 | width: 20px; 46 | height: 20px; 47 | border-radius: 200px; 48 | float: left; 49 | } 50 | 51 | .consensus_item_by__description { 52 | color: #979797; 53 | margin-top: 10px; 54 | margin-bottom: 15px; 55 | } 56 | 57 | .text__consensus_status { 58 | display: inline-block; 59 | width: 30%; 60 | text-align: center; 61 | color: #B5B5B5; 62 | padding: 5px; 63 | border-radius: 200px 64 | } 65 | 66 | @media (max-width: 479px) { 67 | .text__consensus_status { 68 | width: 27%; 69 | } 70 | } 71 | 72 | 73 | .text__consensus_status.active { 74 | background-color: var(--SECONDARY_COLOR); 75 | color: white; 76 | } 77 | 78 | .block__consensus_status { 79 | display: block; 80 | background-color: #F2F2F2; 81 | border-radius: 200px; 82 | } 83 | 84 | @media (prefers-color-scheme: dark) { 85 | .block__consensus_status { 86 | background-color: rgb(43, 43, 43) 87 | } 88 | } -------------------------------------------------------------------------------- /_website/static/css/divider.css: -------------------------------------------------------------------------------- 1 | .divider_10 { 2 | width: 100%; 3 | height: 10px; 4 | } 5 | 6 | .divider_20 { 7 | height: 20px; 8 | } 9 | 10 | .divider_100 { 11 | height: 100px; 12 | } 13 | 14 | .inline_divider { 15 | display: inline-block; 16 | width: 20px; 17 | } -------------------------------------------------------------------------------- /_website/static/css/event_slider.css: -------------------------------------------------------------------------------- 1 | .events_slider_section { 2 | display: -webkit-box; 3 | display: -webkit-flex; 4 | display: -ms-flexbox; 5 | display: flex; 6 | overflow: auto; 7 | height: 150px; 8 | padding-top: 10px; 9 | -webkit-box-pack: start; 10 | -webkit-justify-content: flex-start; 11 | -ms-flex-pack: start; 12 | justify-content: flex-start; 13 | -webkit-box-align: center; 14 | -webkit-align-items: center; 15 | -ms-flex-align: center; 16 | align-items: center; 17 | } 18 | 19 | .event_slider_extra_options_block { 20 | padding-right: 80px; 21 | padding-left: 20px; 22 | -webkit-box-flex: 0; 23 | -webkit-flex: 0 0 auto; 24 | -ms-flex: 0 0 auto; 25 | flex: 0 0 auto; 26 | } -------------------------------------------------------------------------------- /_website/static/css/footer.css: -------------------------------------------------------------------------------- 1 | .footer { 2 | padding: 35px 20px; 3 | background-color: #2e2e2e; 4 | color: #fff; 5 | text-align: center; 6 | float: left; 7 | width: 100%; 8 | } 9 | 10 | @media (max-width: 479px) { 11 | .footer { 12 | width: 90%; 13 | } 14 | } 15 | 16 | @media (prefers-color-scheme: dark) { 17 | .footer { 18 | background-color: #1f1f1f 19 | } 20 | } 21 | 22 | 23 | .social_icon { 24 | display: inline-block; 25 | width: 35px; 26 | height: 35px; 27 | min-width: 0px; 28 | margin-right: 5px; 29 | margin-left: 5px; 30 | background-position: 50% 50%; 31 | background-size: contain; 32 | background-repeat: no-repeat; 33 | -webkit-transition: all 200ms ease; 34 | transition: all 200ms ease; 35 | } 36 | 37 | .social_icon:hover { 38 | -webkit-transform: translate(0px, -5px); 39 | -ms-transform: translate(0px, -5px); 40 | transform: translate(0px, -5px); 41 | } 42 | 43 | .social_icon.github { 44 | background-image: url('../images/footer/social_media/github.svg'); 45 | } 46 | 47 | .social_icon.patreon { 48 | background-image: url('../images/footer/social_media/patreon.svg'); 49 | } 50 | 51 | .social_icon.youtube { 52 | background-image: url('../images/footer/social_media/youtube.svg'); 53 | } 54 | 55 | .social_icon.instagram { 56 | background-image: url('../images/footer/social_media/instagram.svg'); 57 | } 58 | 59 | .social_icon.facebook { 60 | background-image: url('../images/footer/social_media/facebook.svg'); 61 | } 62 | 63 | .social_icon.telegram { 64 | background-image: url('../images/footer/social_media/telegram.svg'); 65 | } 66 | 67 | .social_icon.meetup { 68 | background-image: url('../images/footer/social_media/meetup.svg'); 69 | } 70 | 71 | 72 | .footer_half_block { 73 | display: inline-block; 74 | width: 45%; 75 | height: 400px; 76 | padding-right: 10px; 77 | padding-left: 10px; 78 | } 79 | 80 | @media (max-width: 479px) { 81 | .footer_half_block { 82 | width: 100%; 83 | padding-right: 0px; 84 | padding-left: 0px; 85 | } 86 | } 87 | 88 | .hackerspace_map { 89 | height: 180px; 90 | background-image: url('../images/footer/hackerspace_map.jpg'); 91 | background-position: 50% 50%; 92 | background-size: cover; 93 | background-repeat: no-repeat; 94 | display: block; 95 | } -------------------------------------------------------------------------------- /_website/static/css/map.css: -------------------------------------------------------------------------------- 1 | .map_preview { 2 | overflow: hidden; 3 | height: 250px; 4 | border-radius: 20px; 5 | } -------------------------------------------------------------------------------- /_website/static/css/overlays.css: -------------------------------------------------------------------------------- 1 | .dark_overlay { 2 | display: none; 3 | position: fixed; 4 | top: 0; 5 | bottom: 0; 6 | left: 0; 7 | right: 0; 8 | background-color: #00000000; 9 | z-index: 15; 10 | -webkit-transition: all 200ms ease; 11 | transition: all 200ms ease; 12 | opacity: 0; 13 | } 14 | 15 | .dark_overlay.block { 16 | display: block; 17 | } 18 | 19 | .dark_overlay.block.visible { 20 | background-color: #000000d1; 21 | opacity: 1; 22 | } 23 | 24 | .overlay_block { 25 | position: relative; 26 | display: none; 27 | width: 500px; 28 | margin: auto; 29 | margin-top: 22vh; 30 | padding: 20px; 31 | padding-left: 40px; 32 | padding-right: 40px; 33 | background-color: #ececec; 34 | border-radius: 20px; 35 | box-shadow: 0 3px 5px 0 rgba(0, 0, 0, 0.6); 36 | } 37 | 38 | .overlay_block.rtl { 39 | text-align: right; 40 | } 41 | 42 | @media (max-width: 520px) { 43 | .overlay_block { 44 | width: 80%; 45 | padding: 20px; 46 | margin-top: 20px; 47 | padding-top: 5px; 48 | } 49 | } 50 | 51 | @media (prefers-color-scheme: dark) { 52 | .overlay_block { 53 | background-color: rgb(43, 43, 43); 54 | box-shadow: 0 2px 6px 0 rgba(255, 255, 255, 0.25); 55 | } 56 | } -------------------------------------------------------------------------------- /_website/static/images/Liked.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Liked 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /_website/static/images/donate/Patreon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | patreon 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /_website/static/images/donate/cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/static/images/donate/cat.png -------------------------------------------------------------------------------- /_website/static/images/event_default_image.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/static/images/event_default_image.jpeg -------------------------------------------------------------------------------- /_website/static/images/events/event_class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/static/images/events/event_class.png -------------------------------------------------------------------------------- /_website/static/images/events/event_gaming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/static/images/events/event_gaming.png -------------------------------------------------------------------------------- /_website/static/images/events/event_music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/static/images/events/event_music.png -------------------------------------------------------------------------------- /_website/static/images/events/event_sewing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/static/images/events/event_sewing.png -------------------------------------------------------------------------------- /_website/static/images/footer/hackerspace_map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/static/images/footer/hackerspace_map.jpg -------------------------------------------------------------------------------- /_website/static/images/footer/social_media/facebook.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | facebook-logo 5 | Created with Sketch. 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /_website/static/images/footer/social_media/instagram.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | instagram 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /_website/static/images/footer/social_media/meetup.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | meetup 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /_website/static/images/footer/social_media/patreon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | patreon 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /_website/static/images/footer/social_media/telegram.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Telegram 5 | Created with Sketch. 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /_website/static/images/footer/social_media/twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | twitter 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /_website/static/images/footer/social_media/youtube.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | youtube 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /_website/static/images/menu_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Group 2 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /_website/static/images/photo_gallery/flickr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/static/images/photo_gallery/flickr.png -------------------------------------------------------------------------------- /_website/static/images/photo_gallery/google-photos.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_website/static/images/photo_gallery/instagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/static/images/photo_gallery/instagram.png -------------------------------------------------------------------------------- /_website/static/images/photo_gallery/wiki.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/static/images/photo_gallery/wiki.png -------------------------------------------------------------------------------- /_website/static/images/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Path 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /_website/static/images/search/discourse.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | discuss 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /_website/static/images/search/event.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Event 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /_website/static/js/inspace.js: -------------------------------------------------------------------------------- 1 | // Noisebridge specific 2 | function marryspeak(text) { 3 | axios.get('http://pegasus.noise:5000/?text=' + text) 4 | .then(function () {}) 5 | .catch(function () {}) 6 | .finally(function () {}); 7 | } -------------------------------------------------------------------------------- /_website/static/js/menu.js: -------------------------------------------------------------------------------- 1 | function openMenu() { 2 | showOverlay() 3 | document.getElementById('side_menu').classList.add('open') 4 | } 5 | 6 | function switchMenuSelected(menu_item_active) { 7 | const menu_headings = document.getElementsByClassName('menu_heading'); 8 | 9 | Array.prototype.forEach.call(menu_headings, function (heading) { 10 | // Do stuff here 11 | heading.classList.remove('selected') 12 | }); 13 | 14 | document.getElementById(menu_item_active).classList.add('selected') 15 | } 16 | 17 | function getPage(page, menu_item_active) { 18 | closeOverlays() 19 | clearSearch() 20 | request_html('page/' + encodeURI(page.replace(/\//g, '__')), 'page_content', 'inner') 21 | switchMenuSelected(menu_item_active) 22 | window.scrollTo(0, 0); 23 | } -------------------------------------------------------------------------------- /_website/static/js/overlays.js: -------------------------------------------------------------------------------- 1 | function showOverlay(open_overlay = null) { 2 | document.getElementById('dark_overlay').classList.add('block') 3 | setTimeout(function () { 4 | document.getElementById('dark_overlay').classList.add('visible') 5 | }, 200) 6 | 7 | if (open_overlay) { 8 | document.getElementById(open_overlay + '_overlay').style.display = 'block' 9 | } 10 | 11 | } 12 | 13 | function closeOverlays() { 14 | let overlay_blocks = document.getElementsByClassName('overlay_block') 15 | for (block in overlay_blocks) { 16 | if (overlay_blocks[block].style) { 17 | overlay_blocks[block].style.display = 'none' 18 | } 19 | 20 | } 21 | document.getElementById('side_menu').classList.remove('open') 22 | document.getElementById('dark_overlay').classList.remove('visible') 23 | setTimeout(function () { 24 | document.getElementById('dark_overlay').classList.remove('block') 25 | }, 200) 26 | } 27 | 28 | function hideDonateCTA(button) { 29 | button.style.right = '-100px' 30 | setTimeout(() => { 31 | button.style.display = 'none' 32 | }, 200); 33 | } -------------------------------------------------------------------------------- /_website/static/js/tabs.js: -------------------------------------------------------------------------------- 1 | function showActiveTab(tab) { 2 | Array.prototype.forEach.call(document.getElementsByName('tabs'), function (tab) { 3 | // Do stuff here 4 | tab.style.display = 'none' 5 | }); 6 | 7 | Array.prototype.forEach.call(document.getElementsByName('tab_heading'), function (heading) { 8 | // Do stuff here 9 | heading.classList.remove('active') 10 | }); 11 | 12 | document.getElementById('tab__' + tab).style.display = 'block' 13 | document.getElementById('tab_heading__' + tab).classList.add('active') 14 | } -------------------------------------------------------------------------------- /_website/static/js/text_carousel.js: -------------------------------------------------------------------------------- 1 | let TxtRotate = function (el, toRotate, period) { 2 | this.toRotate = toRotate; 3 | this.el = el; 4 | this.loopNum = 0; 5 | this.period = parseInt(period, 10) || 200; 6 | this.txt = ''; 7 | this.tick(); 8 | this.isDeleting = false; 9 | }; 10 | 11 | TxtRotate.prototype.tick = function () { 12 | let i = this.loopNum % this.toRotate.length; 13 | let fullTxt = this.toRotate[i]; 14 | 15 | if (this.isDeleting) { 16 | this.txt = fullTxt.substring(0, this.txt.length - 1); 17 | } else { 18 | this.txt = fullTxt.substring(0, this.txt.length + 1); 19 | } 20 | 21 | this.el.innerHTML = '' + this.txt + ''; 22 | 23 | let that = this; 24 | let delta = 100 - Math.random() * 100; 25 | 26 | if (this.isDeleting) { 27 | delta /= 2; 28 | } 29 | 30 | if (!this.isDeleting && this.txt === fullTxt) { 31 | delta = this.period; 32 | this.isDeleting = true; 33 | } else if (this.isDeleting && this.txt === '') { 34 | this.isDeleting = false; 35 | this.loopNum++; 36 | delta = 500; 37 | } 38 | 39 | setTimeout(function () { 40 | that.tick(); 41 | }, delta); 42 | }; 43 | 44 | function changeText(language) { 45 | let elements = document.getElementsByClassName('txt-rotate'); 46 | for (let i = 0; i < elements.length; i++) { 47 | let toRotate = elements[i].getAttribute('data-rotate'); 48 | let period = elements[i].getAttribute('data-period'); 49 | if (toRotate) { 50 | new TxtRotate(elements[i], JSON.parse(toRotate), period); 51 | } 52 | } 53 | // INJECT CSS 54 | let css = document.createElement("style"); 55 | css.type = "text/css"; 56 | if (language == 'hebrew') { 57 | css.innerHTML = ".txt-rotate > .wrap { border-left: 0.08em solid #666 }"; 58 | } else { 59 | css.innerHTML = ".txt-rotate > .wrap { border-right: 0.08em solid #666 }"; 60 | } 61 | 62 | document.body.appendChild(css); 63 | }; -------------------------------------------------------------------------------- /_website/static/js/translate.js: -------------------------------------------------------------------------------- 1 | function get_name_fields(name_input) { 2 | // request to server: get translation to all languages 3 | axios.get('/apis/hackspace_os/translate', { 4 | params: { 5 | 'q': name_input 6 | } 7 | }) 8 | .then(function (response) { 9 | // show fields for all languages 10 | for (language in response.data) { 11 | document.getElementById('event_name_' + language).value = response.data[language] 12 | } 13 | }) 14 | .catch(function (error) { 15 | console.log(error); 16 | }) 17 | .finally(function () { 18 | // always executed 19 | }); 20 | } 21 | 22 | function translate_description(from_language, to_language) { 23 | // send server request 24 | if (document.getElementById('event_description_' + from_language).value) { 25 | axios.get('/apis/hackspace_os/translate', { 26 | params: { 27 | 'q': document.getElementById('event_description_' + from_language).value, 28 | 'language': to_language 29 | } 30 | }) 31 | .then(function (response) { 32 | document.getElementById('event_description_' + to_language).value = response.data.text 33 | }) 34 | .catch(function (error) { 35 | console.log(error); 36 | }) 37 | .finally(function () { 38 | // always executed 39 | }); 40 | } 41 | } 42 | 43 | function save_language(to_language) { 44 | var CookieDate = new Date; 45 | CookieDate.setFullYear(CookieDate.getFullYear() + 1); 46 | document.cookie = 'lang=' + to_language + '; expires=' + CookieDate.toGMTString() + ';'; 47 | } -------------------------------------------------------------------------------- /_website/static/js/videocall.js: -------------------------------------------------------------------------------- 1 | function load_videocall(room_name, domain) { 2 | const options = { 3 | roomName: room_name, 4 | width: '100%', 5 | height: 500, 6 | parentNode: document.getElementById('videocall') 7 | }; 8 | const api = new JitsiMeetExternalAPI(domain, options); 9 | } -------------------------------------------------------------------------------- /_website/templates/components/SVGs/phone.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | 3 | {% block content %} 4 | 5 | 6 | phone 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/SVGs/plus.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | 3 | {% block content %} 4 | 5 | 6 | Plus 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/SVGs/telegram.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | 3 | {% block content %} 4 | 5 | 6 | telegram 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/consensus_item_preview.html: -------------------------------------------------------------------------------- 1 | {% load text %} 2 | {% block content %} 3 | 4 | 5 |
6 |
by {{ result.one_creator.str_name_en_US|STR__first_name }}
7 |
{{ result.str_name_en_US }}
8 |
{{ result.text_description_en_US|cleanhtml|safe }}
9 |
10 |
New
11 |
Meeting 1 passed
12 | {% if result.str_status == 'approved' %} 13 |
Meeting 2 passed
14 | {% elif result.str_status == 'rejected' %} 15 |
Rejected
16 | {% elif result.str_status == 'archived' %} 17 |
Archived
18 | {% else %} 19 |
Meeting 2 passed
20 | {% endif %} 21 |
22 |
23 | 24 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/consensus_items_entries.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | 3 | {% for result in all_items %} 4 | {% include "components/body/consensus_item_preview.html" %} 5 | {% endfor %} 6 |
7 | 8 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/edit_this_page.html: -------------------------------------------------------------------------------- 1 | {% load text %} 2 | {% load config %} 3 | {% load translate %} 4 | {% block content %} 5 | 6 |
7 | {% if selected and user.is_authenticated %} 8 |
{{ 'Edit this database entry!'|landingpage:language }}
9 | {{ 'Open admin interface'|landingpage:language }} 10 | {% endif %} 11 | {% if 'WEBSITE.WEBSITE_GIT'|get_config %} 12 |
13 | {% if page_git_url %} 14 |
{{ 'Edit this page!'|landingpage:language }}
15 | {{ 'Click here!'|landingpage:language }} 16 | {% else %} 17 |
{{ 'Edit our website!'|landingpage:language }}
18 | {{ 'Click here!'|landingpage:language }} 19 | {% endif %} 20 |
21 |
22 |
{{ 'Edit the text & translations!'|landingpage:language }}
23 | {{ 'Click here!'|landingpage:language }} 24 | {% endif %} 25 |
26 | 27 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/event_new/form_elements/dropdown_field.html: -------------------------------------------------------------------------------- 1 | {% load translate %} 2 | {% block content %} 3 | 4 |

{{ field_heading|events:language|safe }}

5 |
6 | 12 |
13 | 14 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/event_new/form_elements/expected_crowd_field.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 |

{{ field_heading|events:language|safe }}

6 |
7 | 14 | 15 | 23 | 24 |
25 | 26 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/event_new/form_elements/hosts_field.html: -------------------------------------------------------------------------------- 1 | {% load secrets %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 |

{{ field_heading|events:language|safe }}

6 |
{{ 'Select the host...'|events:language|safe }}
7 |
8 | 9 | 13 | 14 | 15 | 16 | 17 |
18 |
19 | 20 |
21 | 22 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/event_new/form_elements/location_field.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 |

{{ field_heading|events:language|safe }}

6 | {% if field_subheading %} 7 |
{{ field_subheading|events:language|safe }}
8 | {% endif %} 9 |
10 | 21 | 22 | 23 |
24 | 25 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/event_new/form_elements/overlapping_events.html: -------------------------------------------------------------------------------- 1 | {% load translate %} 2 | {% block content %} 3 | 4 |

Overlap

5 |
6 | Your event seems to overlap with {{ overlapping_events.overlapping_events|length }} existing event{% if overlapping_events.overlapping_events|length > 1 %}s{% endif %}.
7 | Consider changing the space, date, time or duration. 8 |
9 |
10 | 11 |
12 |
13 | {% for time in overlapping_events.times %} 14 |
{{ time.str_readable }}
15 | {% endfor %} 16 |
17 |
18 |
19 | Your event 20 |
21 |
22 | {% for event in overlapping_events.overlapping_events %} 23 | 28 | {% endfor %} 29 |
30 | 31 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/event_new/form_elements/publish_options_field.html: -------------------------------------------------------------------------------- 1 | {% load translate %} 2 | {% block content %} 3 | 4 |

{{ field_heading|events:language|safe }}

5 |
6 | 7 |
8 | 9 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/event_new/form_elements/repeating_field.html: -------------------------------------------------------------------------------- 1 | {% load translate %} 2 | {% block content %} 3 | 4 |

{{ field_heading|events:language|safe }}

5 |
6 | 12 | 18 | 19 |
20 | 21 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/event_new/form_elements/text_field.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 |

{{ field_heading|events:language|safe }}

6 | {% if field_subheading %} 7 |
{{ field_subheading|events:language|safe }}
8 | {% endif %} 9 |
10 | 11 | {% if multi_language == True %} 12 | 13 | {% with LANGUAGES='WEBSITE.LANGUAGES'|get_config %} 14 | 15 | {% if LANGUAGES|length > 1 %} 16 |
{{ language|events:language|title }}
17 | {% endif %} 18 | 19 |
20 | 21 | {% for alllanguage in LANGUAGES %} 22 | 23 | {% if alllanguage != language %} 24 |
{{ alllanguage|events:language|title }}
25 |
{{ 'Auto translate'|events:language|safe }}
26 | 27 |
28 | {% endif %} 29 | 30 | {% endfor %} 31 | {% endwith %} 32 | 33 | {% else %} 34 | 35 | 36 |
37 | 38 | {% endif %} 39 | 40 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/event_new/form_elements/upload_image_field.html: -------------------------------------------------------------------------------- 1 | {% load translate %} 2 | {% load secrets %} 3 | {% block content %} 4 | 5 |

{{ field_heading|events:language|safe }}

6 | 7 | {% if field_subheading %} 8 |
{{ field_subheading|events:language|safe }}
9 | {% endif %} 10 |
11 | 12 |
13 | 14 | 15 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/event_new/form_elements/volunteers_field.html: -------------------------------------------------------------------------------- 1 | {% load translate %} 2 | {% block content %} 3 | 4 |

{{ field_heading|events:language|safe }}

5 |
{{ 'Can you need volunteers?...'|events:language|safe }}
6 |
7 | 11 | 12 |
13 | 14 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/event_new/hosts_search_results.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | 3 | {% for host in all_hosts %} 4 |
5 |
6 |
{{ host.str_name_shortened }}
7 |
8 | {% endfor %} 9 | 10 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/events_slider.html: -------------------------------------------------------------------------------- 1 | {% load translate %} 2 | {% load config %} 3 | {% block content %} 4 | 5 |
6 |
7 | {% for result in upcoming_events %} 8 | {% include "components/body/result_preview_block.html" %} 9 | {% endfor %} 10 |
11 | {% if upcoming_events %} 12 | {{ 'Show all'|landingpage:language|safe }} 13 |
14 | {% endif %} 15 | {% if 'EVENTS.ALLOW_IN_SPACE_EVENTS'|get_config or 'EVENTS.ALLOW_ONLINE_EVENTS'|get_config or 'EVENTS.ALLOW_OTHER_EVENT_LOCATIONS'|get_config %} 16 | 17 |
{% include "components/SVGs/plus.html" %}
18 | {% if 'EVENTS.ALLOW_IN_SPACE_EVENTS'|get_config or 'EVENTS.ALLOW_OTHER_EVENT_LOCATIONS'|get_config %} 19 | {{ 'Create an event'|landingpage:language|safe }} 20 | {% else %} 21 | {{ 'Create an online-event'|landingpage:language|safe }} 22 | {% endif %} 23 |
24 | {% endif %} 25 |
26 |
27 | 28 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/landing_contact_us.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 |
6 |

{{ 'Contact us!'|landingpage:language|safe }}

7 |

{{ 'Contact us... text'|landingpage:language|safe }}

8 | 9 | {% if 'CONTACT.PHONE_NUMBER'|get_config %} 10 | 11 |
{% include "components/SVGs/phone.html" %}
12 | 13 |
14 | {% endif %} 15 | 16 | {% with EMAIL='CONTACT.E_MAIL'|get_config %} 17 | {% if EMAIL %} 18 | 19 |
{% include "components/SVGs/email.html" %}
20 | 21 |
22 | {% endif %} 23 | {% endwith %} 24 | 25 | {% if 'CONTACT.TELEGRAM_GROUPS'|get_config %} 26 | {% for GROUP in 'CONTACT.TELEGRAM_GROUPS'|get_config %} 27 | 28 |
{% include "components/SVGs/telegram.html" %}
29 | 30 |
31 | {% endfor %} 32 | {% endif %} 33 | 34 |
35 |
36 |
37 | 38 |
39 | 40 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/landing_do_i_belong.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 |
6 |

{{ 'Do I belong at SPACE?'|landingpage:language|safe }}

7 |

{{ 'YES you do as long...'|landingpage:language|safe }}

8 |
9 | 10 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/landing_please_donate.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 |
6 |
7 |

{{ 'SPACE wouldnt exist without your support!'|landingpage:language|safe }}

8 |
9 |
{{ 'Donate'|landingpage:language|safe }}
10 |
11 |
12 | 13 |
14 | 15 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/meetings/current_meeting.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 |
6 |
7 | {% if current_meeting %} 8 |

{{ 'Join todays meeting!'|meetings:language }}

9 |

{{ 'Join us now...'|meetings:language|safe }}

10 | {% else %} 11 |

{{ 'Starting new meeting ...'|meetings:language|safe }}

12 | {% endif %} 13 |
14 |
15 | {% if current_meeting %} 16 |

{{ current_meeting.text_date }}

17 | {{ 'Presentation mode'|meetings:language }} 18 |
19 | 20 |
21 | {% if 'VIDEOCALLS.JITSI_DOMAIN'|get_config %} 22 |
23 |
24 |
25 | {% endif %} 26 | {% else %} 27 |

28 | {{ 'Starting a new meeting based on...'|meetings:language|safe }} 29 |

30 | {% endif %} 31 |
32 |
33 |

34 | {{ 'Did you know? Keywords?'|meetings:language|safe }} 35 |

36 |
37 |
38 | 39 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/meetings/meetings_list.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | 3 | {% for note in past_meetings %} 4 | 5 |

{{ note.text_date }}

6 | {% if note.text_keywords %} 7 |
Keywords:
8 |

{{ note.text_keywords }}

9 | {% endif %} 10 |
11 | {% endfor %} 12 |
13 | 14 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/meetings/next_meeting.html: -------------------------------------------------------------------------------- 1 | {% load translate %} 2 | {% block content %} 3 | 4 |
5 | {% if next_meeting %} 6 |

{% if current_meeting %}{{ 'Or join'|meetings:language }}{% else %}{{ 'Join'|meetings:language }}{% endif %} {{ 'our next meeting!'|meetings:language }}

7 |
8 | {% include "components/body/result_preview_block.html" with result=next_meeting %} 9 | {% endif %} 10 |
11 |

12 | {% if not current_meeting %} 13 | {{ 'Click here to manually start a new meeting'|meetings:language }} 14 | {% endif %} 15 |

16 |
17 | 18 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/meetings/past_meetings.html: -------------------------------------------------------------------------------- 1 | {% load translate %} 2 | {% block content %} 3 | 4 |
5 |

{{ 'Previous meeting notes'|meetings:language }}

6 | {% if past_meetings %} 7 | 8 | {% include "components/body/meetings/meetings_list.html" %} 9 | 10 | 15 | {% else %} 16 | {{ 'No meeting notes yet.'|meetings:language }} 17 | {% endif %} 18 |
19 | 20 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/photos_list.html: -------------------------------------------------------------------------------- 1 | {% load text %} 2 | {% block content %} 3 | 4 | {% for photo in photos %} 5 | 7 |
8 | {% if overlays != False %} 9 |
10 |
{{ photo.str_source }}
11 | {% if photo.text_description_en_US %} 12 |
{{ photo.text_description_en_US }}
13 | {% endif %} 14 |
{{ photo.str_relative_time }}
15 |
16 | {% endif %} 17 |
18 | {% endfor %} 19 |
20 | 21 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/result_preview_block.html: -------------------------------------------------------------------------------- 1 | {% load text %} 2 | 3 | {% block content %} 4 | 5 | 6 | {% if result.text_series_timing %} 7 |
{{ result.str_series }}
8 | {% endif %} 9 | {% if result.str_relative_time %} 10 |
{% if result.boolean_online_meetup %}Online, {% endif %}{{ result.str_relative_time }}
11 | {% endif %} 12 |
13 |
14 | {% if language == 'hebrew' and result.str_name_he_IL %} 15 | {{ result.str_name_he_IL|shorten:30|safe }} 16 | {% else %} 17 | {{ result.str_name_en_US|shorten:30|safe }} 18 | {% endif %} 19 |
20 |
{{ result.datetime_range_text }}
21 |
22 | 23 |
24 | 25 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/results_list_entries.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | 3 | {% if all_results != True %} 4 | {% for result in all_results %} 5 | {% include "components/body/result_preview_block.html" with change_contrast=True %} 6 | {% endfor %} 7 |
8 | {% endif %} 9 | 10 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/body/wish_preview.html: -------------------------------------------------------------------------------- 1 | {% load text %} 2 | 3 | {% block content %} 4 | 5 | 6 | 7 | 8 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/discourse/event_post.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | 3 | {% block content %} 4 | 5 | {% if result.str_series_repeat_how_often %} 6 | **When?** 7 | 🗓{{ result.repeating }} | {{ result.time_range }} 8 | {% else %} 9 | **When?** 10 | {{ result.datetime_range }}
11 | {% endif %} 12 | 13 | **Where?** 14 | {{ result.str_location|safe }}
15 | 16 | {% with ADDRESS='PHYSICAL_SPACE.ADDRESS'|get_config %} 17 | {% if ADDRESS.STREET in result.str_location %} 18 | **How to find us?** 19 | {{ ADDRESS.HOW_TO_FIND_US__english }}
20 | {% endif %} 21 | {% endwith %} 22 | 23 | **Price?** 24 | Free
25 | 26 | **Organizers?** 27 | {% for host in result.many_hosts.all %}[{{ host.str_name_en_US }}]({{ host.url_discourse }})
{% endfor %} 28 | 29 | {% if result.boolean_looking_for_volunteers == True %} 30 | **Looking for volunteers?** 31 | YES!! Please reply to this event post if you are interested in helping! 32 | {% else %} 33 | **Looking for volunteers?** 34 | No. 35 | {% endif %} 36 | 37 | *** 38 | {% if result.url_featured_photo or 'WEBSITE.DOMAIN'|get_config in result.image_featured_photo.url %} 39 |
40 | image 41 | {% endif %} 42 | 43 | {% if result.text_description_en_US %} 44 | {{ result.text_description_en_US }}
45 | {% endif %} 46 | 47 | *** 48 | {{ 'EVENTS.DISCOURSE_AND_MEETUP_EVENT_FOOTER_HTML'|get_config|safe }} 49 | 50 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/head/css.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | {% load css %} 3 | {% load config %} 4 | 5 | {% block content %} 6 | 7 | 16 | 17 | {% for file_name in ''|getCSSfiles %} 18 | 19 | {% endfor %} 20 | 21 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/head/favicons.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | {% block content %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/head/head.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | {% block content %} 4 | 5 | 6 | 7 | {% include "components/head/meta.html" %} 8 | {% include "components/head/css.html" with css_files=css_files %} 9 | {% include "components/head/js.html" %} 10 | {% include "components/head/favicons.html" %} 11 | 12 | 13 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/head/meta.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | {% block content %} 4 | 5 | 6 | {{ page_name }} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/header/temporary_info.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | 3 | {% block content %} 4 | 5 | {% if ''|still_temporary_open_status %} 6 | {% if 'PHYSICAL_SPACE.TEMPORARY_LANDINGPAGE_HEADER.INFO_MINI_HEADER'|get_config %} 7 | {% if 'PHYSICAL_SPACE.TEMPORARY_LANDINGPAGE_HEADER.INFO_POPUP'|get_config %} 8 |
{{ 'PHYSICAL_SPACE.TEMPORARY_LANDINGPAGE_HEADER.INFO_MINI_HEADER'|get_config }}
Click here for more details.
9 | {% else %} 10 |
{{ 'PHYSICAL_SPACE.TEMPORARY_LANDINGPAGE_HEADER.INFO_MINI_HEADER'|get_config }}
11 | {% endif %} 12 | {% endif %} 13 | {% endif %} 14 | 15 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/overlays/meeting_over.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 |
6 |

{{ 'Is the meeting over?'|meetings:language|safe }}

7 |
{{ 'If yes... meeting will be saved...'|meetings:language|safe }}
8 |
9 | 12 |
13 | 14 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/overlays/temporary_info.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | 3 | {% block content %} 4 | 5 |
6 | 7 | 8 |

Important announcement

9 |
{{ 'PHYSICAL_SPACE.TEMPORARY_LANDINGPAGE_HEADER.INFO_POPUP'|get_config }}
10 | 11 |
12 | 13 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/search/search_result.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | 3 | {{ result.name|safe }} 4 | 5 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/components/search/search_results.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | 3 | {% for result in search_results %} 4 | {% include "components/search/search_result.html" %} 5 | {% endfor %} 6 | 7 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/event_banner_view.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 | {% include "components/head/head.html" with css_files=css_files %} 6 | 7 | 8 | {% if selected.url_featured_photo %} 9 |
10 | {% elif selected.image_featured_photo %} 11 |
12 | {% endif %} 13 |
14 | Soon at TAMI: 15 |
16 |
17 |
{{ selected.str_name_en_US|safe }}
18 |
{{ selected.datetime_range_text }}
19 |
20 | 23 | 24 | 25 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/event_new_view.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 | {% include "components/header/temporary_info.html" %} 6 | 7 |
8 |
9 |
10 |
11 | 12 |
13 | 14 |
15 |
16 |

{{ 'What event do you want to organize?'|events:language|safe }}

17 | 18 |
19 | 20 |
21 |
22 |
23 | 24 |
25 |
26 | 27 |
28 | 29 | 36 | 37 |
38 |
39 |
40 | 41 | 44 | 45 | 46 | {% include "components/body/edit_this_page.html" %} 47 | 48 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/landingpage_view.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% block content %} 3 | 4 | {% include "components/header/temporary_info.html" %} 5 | 6 | {% include "components/header/landingpage.html" %} 7 | {% if 'Events|View' in 'MODULES'|get_config %} 8 | {% include "components/body/events_slider.html" %} 9 | {% endif %} 10 |
11 | {% include "components/body/quick_access_icons.html" %} 12 |
13 | {% include "components/body/landing_do_i_belong.html" %} 14 |
15 | 16 | {% if in_space == False %} 17 | {% include "components/body/landing_visit_us.html" %} 18 | 19 | {% if 'CONTACT.PHONE_NUMBER'|get_config or 'CONTACT.E_MAIL'|get_config or 'CONTACT.TELEGRAM_GROUPS'|get_config %} 20 | {% include "components/body/landing_contact_us.html" %} 21 | {% endif %} 22 | 23 | {% endif %} 24 | 25 | {% if 'BASICS.DONATION_URLs.MONEY'|get_config %} 26 | {% include "components/body/landing_please_donate.html" %} 27 | {% endif %} 28 | 29 | {% include "components/body/edit_this_page.html" %} 30 | 31 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/machine_view.html: -------------------------------------------------------------------------------- 1 | {% load array %} 2 | {% load text %} 3 | {% load translate %} 4 | {% block content %} 5 | 6 | {% include "components/header/temporary_info.html" %} 7 | 8 |
9 |
10 |
14 |
15 | 16 |
17 |
18 |

{{ selected.str_name_en_US }}

19 |
20 | {% if selected.text_description_en_US %} 21 | {{ selected.text_description_en_US|findSearches:'Searching ...'|landingpage:language|safe }}
22 |
23 | {% endif %} 24 | {% if selected.url_wiki %} 25 | Show full wiki page 26 | {% endif %} 27 |
28 |
29 | 30 |
31 |
32 | 33 |
34 |
35 | 36 |
37 |
38 | {% if selected.one_guilde %} 39 |
40 |

Guilde

41 | {% include "components/body/result_preview_block.html" with change_contrast=True result=selected.one_guilde %} 42 |
43 | {% endif %} 44 | {% if selected.one_space %} 45 |
46 |

Space

47 | {% include "components/body/result_preview_block.html" with change_contrast=True result=selected.one_space %} 48 |
49 | {% endif %} 50 |
51 |
52 | 53 | 54 |
55 | 56 | {% include "components/body/edit_this_page.html" %} 57 | 58 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/meeting_present.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 | {% include "components/head/head.html" with css_files=css_files %} 6 | 7 | 8 | 9 |
10 | {% include "components/overlays/meeting_over.html" %} 11 |
12 | 13 |
14 | 15 |
16 |
17 |
Currently:
18 | 19 | {% for main_topic in current_meeting.list_main_topics %} 20 |
1 %} style="display: none"{% endif %}> 21 |

{{ main_topic }}

22 | {% if main_topic == 'Discussion' %} 23 | 24 | {% endif %} 25 |
26 | {% endfor %} 27 |
28 | 29 |
30 | Next topic 31 |
32 |
33 |
34 |
35 |
Live
36 |
37 | 38 | {% if 'WEBSITE.DOMAIN'|get_config in request.META.HTTP_HOST %}https://{% else %}http://{% endif %} 39 | {{ request.META.HTTP_HOST }}/meeting
40 |
41 | End meeting 42 | 43 | 44 | 45 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/meeting_view.html: -------------------------------------------------------------------------------- 1 | {% load text %} 2 | {% load translate %} 3 | 4 | {% block content %} 5 | 6 | {% include "components/header/temporary_info.html" %} 7 | 8 |
9 |
10 |

{{ 'Meeting Notes'|meetings:language }} | {{ selected.text_date }}

11 |

{{ 'Keywords'|meetings:language }}:

12 |
13 |
14 | {% if selected.text_keywords%} 15 | {% for keyword in selected.text_keywords|split:',' %} 16 | {{ keyword }} 17 | {% endfor %} 18 | {% endif %} 19 |
20 | Add 21 | 22 | 23 |
24 | {% if '
{{ selected.text_notes }} 28 | {% endif %} 29 |
30 |
31 |
32 |
33 | {% include "components/body/meetings/next_meeting.html" %} 34 |
35 | {% include "components/body/meetings/past_meetings.html" %} 36 |
37 | 38 | {% include "components/body/edit_this_page.html" %} 39 | 40 | 41 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/meetings_view.html: -------------------------------------------------------------------------------- 1 | {% block content %} 2 | 3 | {% include "components/header/temporary_info.html" %} 4 | 5 |
6 |
7 |
8 |
9 | {% if current_meeting %} 10 | {% include "components/body/meetings/current_meeting.html" %} 11 | {% endif %} 12 |
13 | {% include "components/body/meetings/next_meeting.html" %} 14 |
15 | {% include "components/body/meetings/past_meetings.html" %} 16 | 17 | {% include "components/body/edit_this_page.html" %} 18 | 19 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/page.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load translate %} 3 | {% block content %} 4 | 5 | {% include "components/head/head.html" with css_files=css_files %} 6 | 7 | 8 | {% include "components/menu.html" %} 9 |
10 |
11 | {% if 'BASICS.DONATION_URLs.MONEY'|get_config %} 12 | {% include "components/overlays/donate.html" %} 13 | {% endif %} 14 | 15 | {% if ''|still_temporary_open_status and 'PHYSICAL_SPACE.TEMPORARY_LANDINGPAGE_HEADER.INFO_POPUP'|get_config %} 16 | {% include "components/overlays/temporary_info.html" %} 17 | {% endif %} 18 |
19 | 20 | {% if 'BASICS.DONATION_URLs.MONEY'|get_config %} 21 |
{{ 'Donate'|landingpage:language|safe }}
22 | {% if 'BASICS.DONATION_CTA'|get_config %} 23 |
24 | {% endif %} 25 | {% endif %} 26 |
27 | {% if all_results %} 28 | {% include "results_list.html" %} 29 | {% else %} 30 | {% include ""|add:view|add:'.html' %} 31 | {% endif %} 32 |
33 | {% include "components/footer.html" %} 34 |
35 | 36 | 37 | 38 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/photos_view.html: -------------------------------------------------------------------------------- 1 | {% load config %} 2 | {% load text %} 3 | {% load translate %} 4 | {% block content %} 5 | 6 | {% include "components/header/temporary_info.html" %} 7 | 8 | {% with HASHTAG='SOCIAL.HASHTAG'|get_config %} 9 |
{% if HASHTAG %}{{ 'Want to see your photos here?'|photos:language|safe }} {{ 'Use'|photos:language|safe }} {{ HASHTAG }} {{ 'on'|landingpage:language|safe }} Twitter {{ 'or'|landingpage:language|safe }} Instagram.{% endif %}
10 | {% endwith %} 11 |
12 | {% include "components/body/photos_list.html" %} 13 |
14 | 15 | 16 | 22 | 23 |
24 |
{{ 'Latest'|photos:language|safe }}
25 |
{{ 'Oldest'|photos:language|safe }}
26 |
{{ 'Random'|photos:language|safe }}
27 |
28 | 29 |
30 | 31 | {% include "components/body/edit_this_page.html" %} 32 | 33 | {% endblock %} -------------------------------------------------------------------------------- /_website/templates/results_list.html: -------------------------------------------------------------------------------- 1 | {% load translate %} 2 | {% block content %} 3 | 4 | {% include "components/header/temporary_info.html" %} 5 | 6 |
7 |
8 |
9 |
10 | 11 |
12 |

{{ headline|menu:language|safe }}

13 | 14 | {{ description|results_lists:language|safe }} 15 |
16 | {% if wiki_url %} 17 |
18 | Show full wiki page 19 |
20 | {% endif %} 21 |
22 | {% if add_new_requires_user == False or user.is_authenticated %} 23 | {{ addnew_text|results_lists:language|safe }} 24 | {% endif %} 25 |
26 |
27 |
28 |
29 | 30 |
31 |
32 | 33 |
34 |
35 | {% include "components/body/results_list_entries.html" %} 36 | 37 | {% if results_count > 10 %} 38 | {{ 'Show more'|landingpage:language|safe }} 39 | {% endif %} 40 |
41 |
42 | 43 |
44 | 45 | {% include "components/body/edit_this_page.html" %} 46 | 47 | 48 | {% endblock %} -------------------------------------------------------------------------------- /_website/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/templatetags/__init__.py -------------------------------------------------------------------------------- /_website/templatetags/array.py: -------------------------------------------------------------------------------- 1 | from django.template import Library 2 | 3 | register = Library() 4 | 5 | 6 | @register.filter 7 | def upto(array, number): 8 | if not array: 9 | return [] 10 | return array[:number] 11 | -------------------------------------------------------------------------------- /_website/templatetags/config.py: -------------------------------------------------------------------------------- 1 | from django.template import Library 2 | from _setup.models import Config 3 | from _apis.models.hackspaceOS_functions.open_status import OpenStatus 4 | 5 | register = Library() 6 | 7 | 8 | @register.filter 9 | def get_config(key_name): 10 | return Config(key_name).value 11 | 12 | 13 | @register.filter 14 | def still_temporary_open_status(input): 15 | return OpenStatus(None).still_temporary 16 | -------------------------------------------------------------------------------- /_website/templatetags/css.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from os import listdir 3 | from os.path import isfile, join 4 | 5 | from django.template import Library 6 | 7 | register = Library() 8 | 9 | 10 | @register.filter 11 | def getCSSfiles(placeholder): 12 | css_files = [f.replace('.css', '') for f in listdir(join( 13 | sys.path[0].split('HackspaceOSVenv')[0], '_website/static/css')) if isfile(join(join( 14 | sys.path[0].split('HackspaceOSVenv')[0], '_website/static/css'), f))] 15 | return css_files 16 | 17 | 18 | @register.filter 19 | def getCSSpath(filename): 20 | return 'css/'+filename+'.css' 21 | 22 | 23 | @register.filter 24 | def image_exists(filename): 25 | return isfile(join(sys.path[0].split('HackspaceOSVenv')[0], '_website/static/images/'+filename)) 26 | -------------------------------------------------------------------------------- /_website/templatetags/js.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from django.template import Library 3 | from os import listdir 4 | from os.path import isfile, join 5 | register = Library() 6 | 7 | 8 | @register.filter 9 | def getJSfiles(placeholder): 10 | js_files = [f.replace('.js', '') for f in listdir(join( 11 | sys.path[0].split('HackspaceOSVenv')[0], '_website/static/js')) if isfile(join(join( 12 | sys.path[0].split('HackspaceOSVenv')[0], '_website/static/js'), f))] 13 | return js_files 14 | 15 | 16 | @register.filter 17 | def getJSpath(filename): 18 | return 'js/'+filename+'.js' 19 | -------------------------------------------------------------------------------- /_website/templatetags/secrets.py: -------------------------------------------------------------------------------- 1 | from django.template import Library 2 | from _setup.models import Secret 3 | 4 | register = Library() 5 | 6 | 7 | @register.filter 8 | def key_exists(str_key_name): 9 | return Secret(str_key_name).exists 10 | 11 | 12 | @register.filter 13 | def get_key(str_key_name): 14 | return Secret(str_key_name).value 15 | -------------------------------------------------------------------------------- /_website/templatetags/socialnetworks.py: -------------------------------------------------------------------------------- 1 | from django.template import Library 2 | 3 | register = Library() 4 | 5 | 6 | @register.filter 7 | def getTwitterUsername(socialaccounts): 8 | for social in socialaccounts: 9 | if social['name'] == 'Twitter': 10 | return social['url'].split('twitter.com/')[1] 11 | 12 | 13 | @register.filter 14 | def exists(socialaccounts, socialaccount): 15 | for social in socialaccounts: 16 | if social['name'] == socialaccount: 17 | return True 18 | -------------------------------------------------------------------------------- /_website/templatetags/translate.py: -------------------------------------------------------------------------------- 1 | from django.template import Library 2 | register = Library() 3 | 4 | 5 | @register.filter 6 | def landingpage(text, language): 7 | from django.template.loader import get_template 8 | return get_template('landingpage.html').render({ 9 | 'word': text, 10 | 'language': language 11 | }).lstrip().rstrip() 12 | 13 | 14 | @register.filter 15 | def donate(text, language): 16 | from django.template.loader import get_template 17 | return get_template('donate.html').render({ 18 | 'word': text, 19 | 'language': language 20 | }).lstrip().rstrip() 21 | 22 | 23 | @register.filter 24 | def menu(text, language): 25 | from django.template.loader import get_template 26 | return get_template('menu.html').render({ 27 | 'word': text, 28 | 'language': language 29 | }).lstrip().rstrip() 30 | 31 | 32 | @register.filter 33 | def values(text, language): 34 | from django.template.loader import get_template 35 | return get_template('values.html').render({ 36 | 'word': text, 37 | 'language': language 38 | }).lstrip().rstrip() 39 | 40 | 41 | @register.filter 42 | def results_lists(text, language): 43 | from django.template.loader import get_template 44 | return get_template('results_lists.html').render({ 45 | 'word': text, 46 | 'language': language 47 | }).lstrip().rstrip() 48 | 49 | 50 | @register.filter 51 | def events(text, language): 52 | from django.template.loader import get_template 53 | return get_template('events.html').render({ 54 | 'word': text, 55 | 'language': language 56 | }).lstrip().rstrip() 57 | 58 | 59 | @register.filter 60 | def photos(text, language): 61 | from django.template.loader import get_template 62 | return get_template('photos.html').render({ 63 | 'word': text, 64 | 'language': language 65 | }).lstrip().rstrip() 66 | 67 | 68 | @register.filter 69 | def meetings(text, language): 70 | from django.template.loader import get_template 71 | return get_template('meetings.html').render({ 72 | 'word': text, 73 | 'language': language 74 | }).lstrip().rstrip() 75 | 76 | 77 | @register.filter 78 | def get_language_local_name(language): 79 | languages = { 80 | 'english': 'English', 81 | 'hebrew': 'עברית', 82 | 'german': 'Deutsch' 83 | } 84 | return languages[language] 85 | -------------------------------------------------------------------------------- /_website/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glowingkitty/HackspaceOS/29621a5f5daef7a8073f368b7d95a1df654c8ba9/_website/tests/__init__.py -------------------------------------------------------------------------------- /_website/views/__init__.py: -------------------------------------------------------------------------------- 1 | from _website.views.consensus_view import ConsensusView 2 | from _website.views.events_view import EventsView 3 | from _website.views.guildes_view import GuildesView 4 | from _website.views.landingpage_view import LandingpageView 5 | from _website.views.machines_view import MachinesView 6 | from _website.views.meetings_view import MeetingsView 7 | from _website.views.photos_view import PhotosView 8 | from _website.views.projects_view import ProjectsView 9 | from _website.views.spaces_view import SpacesView 10 | from _website.views.values_view import ValuesView 11 | from _website.views.logout_view import LogoutView 12 | -------------------------------------------------------------------------------- /_website/views/consensus_view.py: -------------------------------------------------------------------------------- 1 | from _website.views.view import View 2 | from django.shortcuts import render 3 | from _website.models import Request 4 | from django.template.loader import get_template 5 | 6 | 7 | class ConsensusView(View): 8 | def get_context(self, request): 9 | self.log('ConsensusView.get_context()') 10 | from _database.models import Consensus 11 | 12 | request = Request(request) 13 | self.context = { 14 | 'view': 'consensus_view', 15 | 'in_space': request.in_space, 16 | 'hash': request.hash, 17 | 'ADMIN_URL': self.admin_url, 18 | 'user': request.user, 19 | 'language': request.language, 20 | 'auto_search': request.search, 21 | 'slug': '/consensus', 22 | 'page_git_url': '/tree/master/_website/templates/consensus_view.html', 23 | 'page_name': self.space_name+' | Big-C consensus items', 24 | 'page_description': 'When you want to do something that would drastically change '+self.space_name+' (or need a lot of money from Noisebridge for a project) - suggest a Big-C consensus item!', 25 | 'all_current_items': Consensus.objects.current(), 26 | 'all_current_items_count': Consensus.objects.current().count(), 27 | 'all_archived_items': Consensus.objects.archived(), 28 | 'all_archived_items_count': Consensus.objects.archived().count(), 29 | } 30 | 31 | def get(self, request): 32 | self.log('ConsensusView.get()') 33 | self.get_context(request) 34 | return render(request, 'page.html', self.context) 35 | 36 | def html(self): 37 | self.log('ConsensusView.html()') 38 | return { 39 | 'html': get_template(self.context['view']+'.html').render(self.context), 40 | 'page_name': self.context['page_name'] 41 | } 42 | -------------------------------------------------------------------------------- /_website/views/handler_404_view.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import redirect 2 | from _website.views.view import View 3 | 4 | 5 | def handler404(request, exception, template_name="404.html"): 6 | return redirect('/?search='+request.path[1:]) 7 | -------------------------------------------------------------------------------- /_website/views/landingpage_view.py: -------------------------------------------------------------------------------- 1 | from _website.views.view import View 2 | from django.shortcuts import render 3 | from _website.models import Request, Response 4 | from django.template.loader import get_template 5 | 6 | 7 | class LandingpageView(View): 8 | def get_context(self, original_request): 9 | self.log('LandingpageView.get_context()') 10 | from _database.models import Event, Photo 11 | from _apis.models.hackspaceOS_functions.open_status import OpenStatus 12 | 13 | request = Request(original_request) 14 | response = Response() 15 | self.context = { 16 | 'view': 'landingpage_view', 17 | 'in_space': request.in_space, 18 | 'hash': request.hash, 19 | 'ADMIN_URL': self.admin_url, 20 | 'user': request.user, 21 | 'language': request.language, 22 | 'auto_search': request.search, 23 | 'slug': '/', 24 | 'page_git_url': '/tree/master/_website/templates/landingpage_view.html', 25 | 'page_name': self.space_name, 26 | 'page_description': response.description, 27 | 'is_open_status': OpenStatus(original_request).value, 28 | 'upcoming_events': Event.objects.QUERYSET__upcoming()[:5], 29 | 'photos': Photo.objects.latest()[:33] 30 | } 31 | 32 | def get(self, request): 33 | self.log('LandingpageView.get()') 34 | self.get_context(request) 35 | return render(request, 'page.html', self.context) 36 | 37 | def html(self): 38 | self.log('LandingpageView.html()') 39 | return { 40 | 'html': get_template(self.context['view']+'.html').render(self.context), 41 | 'page_name': self.context['page_name'] 42 | } 43 | -------------------------------------------------------------------------------- /_website/views/logout_view.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth import logout 2 | from django.shortcuts import redirect 3 | from _website.views.view import View 4 | 5 | 6 | class LogoutView(View): 7 | def get(self, request): 8 | self.log('LogoutView.get()') 9 | logout(request) 10 | return redirect('/') 11 | -------------------------------------------------------------------------------- /_website/views/photos_view.py: -------------------------------------------------------------------------------- 1 | from _website.views.view import View 2 | from _setup.models import Secret 3 | from _setup.models import Config 4 | from django.shortcuts import render 5 | from _website.models import Request 6 | from django.template.loader import get_template 7 | 8 | 9 | class PhotosView(View): 10 | def get_context(self, request): 11 | self.log('PhotosView.get_context()') 12 | from _database.models import Photo 13 | 14 | request = Request(request) 15 | self.context = { 16 | 'view': 'photos_view', 17 | 'in_space': request.in_space, 18 | 'hash': request.hash, 19 | 'ADMIN_URL': self.admin_url, 20 | 'user': request.user, 21 | 'language': request.language, 22 | 'auto_search': request.search, 23 | 'slug': '/photos', 24 | 'page_git_url': '/tree/master/_website/templates/photos_view.html', 25 | 'page_name': self.space_name+' | Photos', 26 | 'page_description': 'Explore '+self.space_name+'\'s history in photos!', 27 | 'photos': Photo.objects.latest()[:30] 28 | } 29 | 30 | def get(self, request): 31 | self.log('PhotosView.get()') 32 | self.get_context(request) 33 | return render(request, 'page.html', self.context) 34 | 35 | def html(self): 36 | self.log('PhotosView.html()') 37 | return { 38 | 'html': get_template(self.context['view']+'.html').render(self.context), 39 | 'page_name': self.context['page_name'] 40 | } 41 | -------------------------------------------------------------------------------- /_website/views/projects_view.py: -------------------------------------------------------------------------------- 1 | from _website.views.view import View 2 | from django.shortcuts import render 3 | from _website.models import Request 4 | from django.template.loader import get_template 5 | 6 | 7 | class ProjectsView(View): 8 | def get_context(self, request): 9 | self.log('ProjectsView.get_context()') 10 | from _database.models import Project 11 | from _setup.models import Secret 12 | 13 | request = Request(request) 14 | 15 | all_results = Project.objects.all()[:10] 16 | self.context = { 17 | 'view': 'results_list', 18 | 'in_space': request.in_space, 19 | 'hash': request.hash, 20 | 'ADMIN_URL': self.admin_url, 21 | 'user': request.user, 22 | 'language': request.language, 23 | 'auto_search': request.search, 24 | 'slug': '/projects', 25 | 'page_git_url': '/tree/master/_database/templates/results_list.html', 26 | 'page_name': self.space_name+' | Projects', 27 | 'page_description': 'People at '+self.space_name+' created all kinds of awesome projects!', 28 | 'headline': 'Projects', 29 | 'description': 'At {} fellow hackers created awesome projects...'.format(self.space_name), 30 | 'wiki_url': None, 31 | 'add_new_requires_user': False, 32 | 'addnew_url': '{}c/projects/'.format(Secret('DISCOURSE.DISCOURSE_URL').value), 33 | 'addnew_text': 'Add project', 34 | 'all_results': all_results if all_results else True, 35 | 'results_count': Project.objects.count(), 36 | 'show_more': 'projects' 37 | } 38 | 39 | def get(self, request): 40 | self.log('ProjectsView.get()') 41 | self.get_context(request) 42 | return render(request, 'page.html', self.context) 43 | 44 | def html(self): 45 | self.log('ProjectsView.html()') 46 | return { 47 | 'html': get_template(self.context['view']+'.html').render(self.context), 48 | 'page_name': self.context['page_name'] 49 | } 50 | -------------------------------------------------------------------------------- /_website/views/values_view.py: -------------------------------------------------------------------------------- 1 | from _website.views.view import View 2 | from _setup.models import Secret 3 | from _setup.models import Config 4 | from django.shortcuts import render 5 | from _website.models import Request 6 | from django.template.loader import get_template 7 | 8 | 9 | class ValuesView(View): 10 | def get_context(self, request): 11 | self.log('ValuesView.get_context()') 12 | request = Request(request) 13 | self.context = { 14 | 'view': 'values_view', 15 | 'in_space': request.in_space, 16 | 'hash': request.hash, 17 | 'ADMIN_URL': self.admin_url, 18 | 'user': request.user, 19 | 'language': request.language, 20 | 'auto_search': request.search, 21 | 'slug': '/values', 22 | 'page_git_url': '/tree/master/_website/templates/values_view.html', 23 | 'page_name': self.space_name+' | Values', 24 | 'page_description': 'Our values at '+self.space_name 25 | } 26 | 27 | def get(self, request): 28 | self.log('ValuesView.get()') 29 | self.get_context(request) 30 | return render(request, 'page.html', self.context) 31 | 32 | def html(self): 33 | self.log('ValuesView.html()') 34 | return { 35 | 'html': get_template(self.context['view']+'.html').render(self.context), 36 | 'page_name': self.context['page_name'] 37 | } 38 | -------------------------------------------------------------------------------- /_website/views/view.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from django.views import View 4 | from pyprintplus import Log 5 | 6 | from _setup.models import Config, Secret 7 | 8 | 9 | class View(View): 10 | logs = ['self.__init__'] 11 | started = round(time.time()) 12 | show_log = True 13 | space_name = Config('BASICS.NAME').value 14 | admin_url = Secret('DJANGO.ADMIN_URL').value 15 | path = '' 16 | 17 | def log(self, text): 18 | import os 19 | self.logs.append(text) 20 | if self.show_log == True: 21 | Log().print('{}'.format(text), os.path.basename(__file__), self.started) 22 | -------------------------------------------------------------------------------- /_website/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for hackspace project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', '_website.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /install.py: -------------------------------------------------------------------------------- 1 | import os 2 | import platform 3 | 4 | system = platform.system() 5 | if system == 'Windows': 6 | print('It seems you are using Windows. Please download Ubuntu or another Linux Subsystem from the Windows 10 AppStore and install the HackspaceOS inside the Linux Subsystem - or alternatively install Linux or MacOS on your device instead.') 7 | else: 8 | main_folder_path = os.path.dirname( 9 | os.path.abspath(__file__)) 10 | python = main_folder_path+"/HackspaceOSVenv/bin/python" 11 | pip = main_folder_path+"/HackspaceOSVenv/bin/pip" 12 | 13 | if os.path.isdir('HackspaceOSVenv') == False: 14 | print('Setting up the Python Virtual Environment...') 15 | os.system('python3 -m venv HackspaceOSVenv') 16 | 17 | print('Installing requirements.txt...') 18 | os.system('cat requirements.txt | xargs -n 1 {} install'.format(pip)) 19 | 20 | print('Start / setup server') 21 | os.system(python+' manage.py runserver') 22 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', '_website.settings') 9 | try: 10 | from django.core.management import execute_from_command_line 11 | except ImportError as exc: 12 | raise ImportError( 13 | "Couldn't import Django. Are you sure it's installed and " 14 | "available on your PYTHONPATH environment variable? Did you " 15 | "forget to activate a virtual environment?" 16 | ) from exc 17 | execute_from_command_line(sys.argv) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp==3.6.2 2 | appdirs==1.4.3 3 | appnope==0.1.0 4 | asgiref==3.2.6 5 | async-timeout==3.0.1 6 | attrs==19.3.0 7 | autopep8==1.5 8 | backcall==0.1.0 9 | beautifulsoup4==4.8.2 10 | bleach==3.1.3 11 | boto3==1.12.27 12 | botocore==1.15.27 13 | bs4==0.0.1 14 | certifi==2019.11.28 15 | chardet==3.0.4 16 | colorclass==2.2.0 17 | croniter==0.3.31 18 | cssselect==1.1.0 19 | decorator==4.4.2 20 | Django==3.0.4 21 | django-appconf==1.0.3 22 | docopt==0.6.2 23 | docutils==0.15.2 24 | emoji==0.5.4 25 | fake-useragent==0.1.11 26 | future==0.18.2 27 | geographiclib==1.50 28 | geopy==1.21.0 29 | gitdb==4.0.2 30 | GitPython==3.1.0 31 | googletrans==2.4.0 32 | httplib2==0.17.0 33 | idna==2.9 34 | idna-ssl==1.1.0 35 | instagram-scraper==1.8.1 36 | ipython==7.13.0 37 | ipython-genutils==0.2.0 38 | jedi==0.16.0 39 | jmespath==0.9.5 40 | lxml==4.5.0 41 | MechanicalSoup==0.12.0 42 | MeetupAPI==1.0.3 43 | multidict==4.7.5 44 | oauthlib==3.1.0 45 | packaging==20.3 46 | parse==1.15.0 47 | parso==0.6.2 48 | pexpect==4.8.0 49 | pickleshare==0.7.5 50 | Pillow==7.0.0 51 | pip-upgrader==1.4.15 52 | prompt-toolkit==3.0.4 53 | ptyprocess==0.6.0 54 | pycodestyle==2.5.0 55 | pyee==7.0.1 56 | Pygments==2.6.1 57 | pyparsing==2.4.6 58 | pyppeteer==0.0.25 59 | pyprintplus==1.0.0 60 | pyquery==1.4.1 61 | python-crontab==2.4.1 62 | python-dateutil==2.8.1 63 | pytz==2019.3 64 | PyWebScraper==0.0.2 65 | rcssmin==1.0.6 66 | requests==2.23.0 67 | requests-html==0.10.0 68 | requests-oauthlib==1.3.0 69 | rjsmin==1.1.0 70 | s3transfer==0.3.3 71 | selenium==3.141.0 72 | six==1.14.0 73 | slackclient==2.5.0 74 | smmap==3.0.1 75 | soupsieve==2.0 76 | sqlparse==0.3.1 77 | terminaltables==3.1.0 78 | tqdm==4.43.0 79 | traitlets==4.3.3 80 | twitter-scraper==0.4.1 81 | typing-extensions==3.7.4.1 82 | urllib3==1.25.8 83 | w3lib==1.21.0 84 | wcwidth==0.1.9 85 | webencodings==0.5.1 86 | websockets==8.1 87 | yarl==1.4.2 88 | -------------------------------------------------------------------------------- /uwsgi_params: -------------------------------------------------------------------------------- 1 | uwsgi_param QUERY_STRING $query_string; 2 | uwsgi_param REQUEST_METHOD $request_method; 3 | uwsgi_param CONTENT_TYPE $content_type; 4 | uwsgi_param CONTENT_LENGTH $content_length; 5 | 6 | uwsgi_param REQUEST_URI $request_uri; 7 | uwsgi_param PATH_INFO $document_uri; 8 | uwsgi_param DOCUMENT_ROOT $document_root; 9 | uwsgi_param SERVER_PROTOCOL $server_protocol; 10 | uwsgi_param REQUEST_SCHEME $scheme; 11 | uwsgi_param HTTPS $https if_not_empty; 12 | 13 | uwsgi_param REMOTE_ADDR $remote_addr; 14 | uwsgi_param REMOTE_PORT $remote_port; 15 | uwsgi_param SERVER_PORT $server_port; 16 | uwsgi_param SERVER_NAME $server_name; 17 | --------------------------------------------------------------------------------