Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/public event #287

Open
wants to merge 41 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
5ef6469
basic restoration of code from a deleted branch. includes- adding is_…
noam-y Feb 11, 2021
885a843
added 2 functions- one to send an adaptable email, with email body co…
noam-y Feb 11, 2021
1f4b084
added front end button to allow users to join event, not connected to…
noam-y Feb 11, 2021
8e0d1ee
adding testing fixtures
noam-y Feb 11, 2021
5a8adeb
adding working user and event fixture, adding is_public param to even…
noam-y Feb 11, 2021
59532d6
subtle changes for debugging add_user_to_event failing tests.
noam-y Feb 11, 2021
235c4b2
added something that prevents adding null event_id to userevent objects.
noam-y Feb 12, 2021
d32ca25
fixed a small bug that made one of the tests fail
noam-y Feb 12, 2021
ef0f679
added func that send email to participants given event id- there are …
noam-y Feb 12, 2021
c6477a5
email not working- last commit before rebuild
noam-y Feb 12, 2021
b7cc686
merged changes
noam-y Feb 12, 2021
540f1bf
merged with current changes + added one func that sends emails to all…
noam-y Feb 14, 2021
49ac8e7
improved documentation
noam-y Feb 14, 2021
e111110
adds feature that makes sure only the event owner can send email to a…
noam-y Feb 14, 2021
573cd2b
Merge branch 'develop' of https://github.com/PythonFreeCourse/calenda…
noam-y Feb 15, 2021
847eb09
merged changes w pulled code
noam-y Feb 15, 2021
b9d6016
Merge branch 'develop' into feature/public_event
yammesicka Feb 18, 2021
e715f4c
merging conflicts
noam-y Feb 18, 2021
14fc7e2
merge with code
noam-y Feb 18, 2021
f515361
trying to add is_public feature to telegram create event bot
noam-y Feb 18, 2021
e4f2ee0
creating more changes to enable public feature on create event func o…
noam-y Feb 18, 2021
9ffa3ea
last chance to add telegram feature- will be deleted soon...
noam-y Feb 18, 2021
e8571f1
reverting changes made on telegram
noam-y Feb 18, 2021
05c90a1
merging changes from pulled code
noam-y Feb 19, 2021
71ee772
changed email sending function to depend on send function so its more…
noam-y Feb 19, 2021
9cf15b1
moving user and event fixtures to conftest.py so we can use them glob…
noam-y Feb 20, 2021
70be019
changing mailing list sender to return the number of emails sent inst…
noam-y Feb 20, 2021
1bc712c
making test to assert failure of sending mailing list with no logged …
noam-y Feb 20, 2021
f371ce1
merging conflicts
noam-y Feb 20, 2021
05310b7
splitting mailing list send to 2 tests- one where no user is logged (…
noam-y Feb 20, 2021
c02ffd0
small pep changes
noam-y Feb 20, 2021
8a58f78
Merge branch 'develop' of https://github.com/PythonFreeCourse/calenda…
noam-y Feb 21, 2021
b6ff758
deleting some visual comments according to yam's commends + hooks
noam-y Feb 21, 2021
093881b
trying to add precommit hooks
noam-y Feb 23, 2021
7b4ee13
merge conflicts
noam-y Feb 25, 2021
986b43b
Merge branch 'feature/public_event' of https://github.com/noam-y/cale…
noam-y Feb 25, 2021
cf5b771
finally merged conflicts
noam-y Feb 26, 2021
76db81a
added guards and small changes
noam-y Feb 26, 2021
9bbed18
Merge branch 'develop' of https://github.com/PythonFreeCourse/calenda…
noam-y Feb 26, 2021
94c4a32
first try of adding koby's user system to event mailing list send
noam-y Feb 26, 2021
b08636e
moving user fixtures from conftest to user_fixtures.
noam-y Feb 26, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions app/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class User(Base):
privacy = Column(String, default="Private", nullable=False)
is_manager = Column(Boolean, default=False)
language_id = Column(Integer, ForeignKey("languages.id"))
availability = Column(Boolean, default=True, nullable=False)

owned_events = relationship(
"Event", cascade="all, delete", back_populates="owner",
Expand Down Expand Up @@ -75,6 +76,7 @@ class Event(Base):
color = Column(String, nullable=True)
all_day = Column(Boolean, default=False)
invitees = Column(String)
is_public = Column(Boolean, default=False)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Event doesn't have "friends" option?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the meaning of friends is different- public event is meant to allow any user in the platform to join the event, just like the public events on facebook. so it means the owner's friends don't matter in this feature :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please explain what is the meaning of public/private event? is it like busy/free?
Thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a pubic event is event anyone can join. it means you don't need to be invited directly from the owner, you can join the event by yourself by clicking a button on event page

emotion = Column(String, nullable=True)
availability = Column(Boolean, default=True, nullable=False)

Expand Down Expand Up @@ -104,8 +106,10 @@ class UserEvent(Base):
__tablename__ = "user_event"

id = Column(Integer, primary_key=True, index=True)
user_id = Column('user_id', Integer, ForeignKey('users.id'))
event_id = Column('event_id', Integer, ForeignKey('events.id'))
user_id = Column('user_id', Integer, ForeignKey(
'users.id'), nullable=False)
event_id = Column('event_id', Integer, ForeignKey(
'events.id'), nullable=False)

events = relationship("Event", back_populates="participants")
participants = relationship("User", back_populates="events")
Expand Down
47 changes: 45 additions & 2 deletions app/internal/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

from app.config import (CALENDAR_HOME_PAGE, CALENDAR_REGISTRATION_PAGE,
CALENDAR_SITE_NAME, email_conf, templates)
from app.database.models import Event, User

from app.database.models import Event, User, UserEvent
from app.internal.utils import get_current_user
noam-y marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use Kobi's user system instead

mail = FastMail(email_conf)


Expand Down Expand Up @@ -52,6 +52,49 @@ def send(
return True


def send_email_to_event_participants(
yammesicka marked this conversation as resolved.
Show resolved Hide resolved
session: Session, event_id: int,
title: str, content: str,
background_tasks: BackgroundTasks = BackgroundTasks
) -> bool:
"""This function is being used to send emails in the background.
it uses the main elements of the func writen above.
It takes an event and a user and it sends the event to the user.
Args:
session(Session): The session to redirect to the database.
title (str): Title of the email that is being sent.
event_id (int): Id number of the event that is used.
content (str): body of email sent.
background_tasks (BackgroundTasks): Function from fastapi that lets
you apply tasks in the background.
Returns:
bool: Returns True if emails were sent, False if none.
"""
event_owner = session.query(Event.owner).filter(id == event_id).first()
if event_owner != get_current_user(session):
return False
# makes sure only event owner can send an email via this func.
mailing_list = session.query(User.email).join(
UserEvent, User.id == UserEvent.user_id
).filter(
event_id == event_id).all()
valid_mailing_list = list(filter(verify_email_pattern, mailing_list))
if not valid_mailing_list:
return False
# making sure app doesn't crash if emails are invalid
event = session.query(Event).get(event_id)
subject = f"{event.title}: {title}"
recipients = valid_mailing_list
body = content
for r in recipients:
print(r)
noam-y marked this conversation as resolved.
Show resolved Hide resolved
background_tasks.add_task(send_internal,
subject=subject,
recipients=r,
body=body)
return True


def send_email_invitation(sender_name: str,
recipient_name: str,
recipient_mail: str,
Expand Down
1 change: 1 addition & 0 deletions app/routers/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from app.internal.email import send as internal_send
from app.internal.email import send_email_invitation


router = APIRouter(
prefix="/email",
tags=["email"],
Expand Down
21 changes: 20 additions & 1 deletion app/routers/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
)
from app.internal import comment as cmt
from app.internal.emotion import get_emotion
from app.internal.utils import create_model, get_current_user
from app.internal.utils import create_model, save, get_current_user
noam-y marked this conversation as resolved.
Show resolved Hide resolved


EVENT_DATA = Tuple[Event, List[Dict[str, str]], str, str]
Expand Down Expand Up @@ -280,6 +280,7 @@ def create_event(db: Session, title: str, start, end, owner_id: int,
vc_link: str = None,
color: Optional[str] = None,
invitees: List[str] = None,
is_public: bool = False,
category_id: Optional[int] = None,
availability: bool = True,
is_google_event: bool = False,
Expand All @@ -300,6 +301,7 @@ def create_event(db: Session, title: str, start, end, owner_id: int,
color=color,
emotion=get_emotion(title, content),
invitees=invitees_concatenated,
is_public=is_public,
all_day=all_day,
category_id=category_id,
availability=availability,
Expand Down Expand Up @@ -398,6 +400,23 @@ def add_new_event(values: dict, db: Session) -> Optional[Event]:
return None


def add_user_to_event(session: Session, user_id: int, event_id: int):
user_already_connected = session.query(UserEvent)\
.filter_by(event_id=event_id, user_id=user_id).all()
noam-y marked this conversation as resolved.
Show resolved Hide resolved
if not user_already_connected:
noam-y marked this conversation as resolved.
Show resolved Hide resolved
""" if user is not registered to the event, the system will add him"""
noam-y marked this conversation as resolved.
Show resolved Hide resolved
association = UserEvent(
user_id=user_id,
event_id=event_id
)
save(session, association)
return True
else:
noam-y marked this conversation as resolved.
Show resolved Hide resolved
# if the user has a connection to the event,
# the function will recognize the duplicate and return false.
return False


def get_template_to_share_event(event_id: int, user_name: str,
db: Session, request: Request) -> templates:
"""Gives shareable template of the event.
Expand Down
37 changes: 36 additions & 1 deletion app/telegram/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,14 @@ async def process_new_event(self, memo_dict):
return await self._process_content(memo_dict)
elif 'location' not in memo_dict:
return await self._process_location(memo_dict)
elif 'is_public' not in memo_dict:
return await self._process_is_public(memo_dict)
elif 'start' not in memo_dict:
return await self._process_start_date(memo_dict)
elif 'end' not in memo_dict:
return await self._process_end_date(memo_dict)
elif 'end' not in memo_dict:
return await self._process_end_date(memo_dict)
elif self.chat.message == 'create':
return await self._submit_new_event(memo_dict)

Expand Down Expand Up @@ -184,7 +188,37 @@ async def _process_content(self, memo_dict):
async def _process_location(self, memo_dict):
memo_dict['location'] = self.chat.message
answer = f'Location:\n{memo_dict["location"]}\n\n'
answer += 'When does it start?'
answer += 'is the event public? (yes\\no)'
await telegram_bot.send_message(
chat_id=self.chat.user_id,
text=answer,
reply_markup=field_kb)
return answer

async def _process_is_public(self, memo_dict):
is_public_response = self.chat.message.lower
if is_public_response in ['yes', 'no']:
print('yasss')
return await self._add_is_public()
return await self._process_bad_bool_input()

async def _process_bad_bool_input(self):
answer = '❗️ Please, enter an answer of yes/no.'
await telegram_bot.send_message(
chat_id=self.chat.user_id,
text=answer,
reply_markup=field_kb)
return answer

async def _add_is_public(self, memo_dict):
if self.chat.message.lower == 'yes':
memo_dict['is_public'] = True
answer = 'public\\private event:\npublic event\n\n'
else:
answer = 'private event'
memo_dict['is_public'] = False
answer = 'public\\private event:\nprivate event\n\n'
answer += '\nWhen does it start?'
await telegram_bot.send_message(
chat_id=self.chat.user_id,
text=answer,
Expand Down Expand Up @@ -248,6 +282,7 @@ async def _submit_new_event(self, memo_dict):
content=memo_dict['content'],
owner_id=self.user.id,
location=memo_dict['location'],
is_public=memo_dict['is_public'],
)
# Delete current session
del telegram_bot.MEMORY[self.chat.user_id]
Expand Down
15 changes: 15 additions & 0 deletions app/templates/event/eventview.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,20 @@
ADD INCLUDE HERE
</div> -->
</div>
<<<<<<< HEAD
noam-y marked this conversation as resolved.
Show resolved Hide resolved
<!-- Copy commented section to add another tab-->
<!-- <div class="tab-pane fade" id="(CHANGE_ME)" role="tabpanel" aria-labelledby="(CHANGE_ME)-tab">-->
<!-- ADD INCLUDE HERE -->
<!-- </div>-->
</div>
<div class="event_info_buttons_row event_info_row_end">
<!-- Buttons could and should be replaced with button-like anchors if need so -->
<button type="button">Duplicate</button>
<button type="button">Edit</button>
{% if event.is_public %}
<button type="button">Join event</button>
{% endif %}
=======
>>>>>>> 8cd3a6e3c8c94ff0e9c86c9a6ed15c9856f757f9
</div>
{% endblock content %}
6 changes: 6 additions & 0 deletions tests/test_a_telegram_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,12 @@ async def test_process_new_event(self):
chat = Chat(gen_message('Universe'))
message = MessageHandler(chat, self.TEST_USER)
answer = 'Location:\nUniverse\n\n'
answer += 'is the event public? (yes\\no)'
assert await message.process_callback() == answer

chat = Chat(gen_message('yes'))
message = MessageHandler(chat, self.TEST_USER)
answer = 'public\\private event:\npublic event\n\n'
answer += 'When does it start?'
assert await message.process_callback() == answer

Expand Down
33 changes: 32 additions & 1 deletion tests/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
from app.dependencies import get_db
from app.internal.utils import delete_instance
from app.main import app

from app.routers.event import add_new_event, add_user_to_event
from app.routers.user import create_user
from app.routers import event as evt


Expand Down Expand Up @@ -138,6 +139,36 @@
]


@pytest.fixture
def new_event(session, new_user):
event = add_new_event(TestApp.event_test_data, session)
return event


@pytest.fixture
def new_user(session):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you can use existing fixtures?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried but didn't really find a proper user fixture inside the file. ill try going over the code again

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are enough user fixtures, use one of the others.

user = create_user(
session=session,
username='new_test_username',
password='new_test_password',
email='new_test.email@gmail.com',
language_id='english'
)

return user


def test_joining_public_event(session, new_event, new_user):
"""test in order to make sure user is added the first time
he asks to join event, yet won't join the same user twice"""
first_join = add_user_to_event(
session, event_id=new_event.id, user_id=new_user.id)
assert first_join
second_join = add_user_to_event(
session, event_id=new_event.id, user_id=new_user.id)
assert not second_join


def test_get_events(event_test_client, session, event):
response = event_test_client.get("/event/")
assert response.ok
Expand Down