Skip to content

Commit

Permalink
Merge branch 'main' into ci-reformatter
Browse files Browse the repository at this point in the history
  • Loading branch information
breed authored May 15, 2024
2 parents 2dc7b75 + b3a7e44 commit 2d674e7
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 48 deletions.
28 changes: 0 additions & 28 deletions .idea/misc.xml

This file was deleted.

44 changes: 44 additions & 0 deletions doc/Group_Feature_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Group Feature

Using the group feature, one can form groups on our Mastodon Server. Using groups, a post can be sent to all the members of that group. Those members don't need to follow the person who made the post.

## Group Creation

It is really easy to create a group on our server. Just follow these steps:-
1. Create a normal user with an email, username and password on our server.
2. Open the Mastodon app on your mobile phone and log into our server as the user you just created.
3. Click on the "Profile" button on the bottom right.
4. Click on "Edit profile" button.
5. Go to the "About" tab.
6. Click on "Add row" button.
7. Under "Label" field, enter "Group" and under "Content" field, enter "True".
8. Click on "Save changes" button.

You now have a new Group!

## Posting using the Group

Note:- Only users who follow the group will be able to make a post on the group.

To make a new post using the group, follow the given steps:-
1. Log into you Mastodon account as a user.
2. Make sure you are following the group.
3. Make a post and tag the group in the post by mentioning "@groupname" in the post.

You will see that the user as well as the group will make the post on the current mastodon server. All the followers of the group will be able to see the group's post.


## Group Deletion

To delete an existing group, follow the given steps:-
1. Log into the Group's Mastodon account using email, username, and password via the Mastodon app.
2. Click on the "Profile" button on the bottom right.
3. Click on "Edit profile" button.
4. Go to the "About" tab.
5. Click on the Delete icon next to the "Group" field.
6. Click on "Save changes" button.

The current user will no longer act as a group.

## Contributors
Ben Reed, Umesh Singh, Atharv Mangal, Nirupama Tippabhatla, Nathan Kim
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import edu.sjsu.moth.server.annotations.RequestObject;
import edu.sjsu.moth.server.db.Account;
import edu.sjsu.moth.server.db.AccountField;
import edu.sjsu.moth.server.db.Follow;
import edu.sjsu.moth.server.service.AccountService;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -18,6 +19,7 @@
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
Expand Down Expand Up @@ -159,6 +161,21 @@ public Mono<ArrayList<Account>> getBlocks(Integer max_id, Integer since_id, Inte
return Mono.just(new ArrayList<Account>());
}


@PostMapping("/api/v1/accounts/{id}/follow")
public Mono<ResponseEntity<Follow>> followUser(@PathVariable("id") String followedId, Principal user){
return accountService.getAccountById(user.getName()).flatMap(a -> accountService.saveFollow(a.id, followedId))
.map(ResponseEntity::ok);
}

@GetMapping("/api/v1/accounts/{id}/following")
public Mono<InboxController.UsersFollowResponse> userFollowing(@PathVariable String id,
@RequestParam(required = false) Integer page,
@RequestParam(required = false) Integer limit) {
return accountService.usersFollow(id, page, limit, "following");
}


private static class RelationshipRequest {
public String[] id;
public Boolean with_suspended;
Expand Down
4 changes: 4 additions & 0 deletions server/src/main/java/edu/sjsu/moth/server/db/Follow.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ public FollowKey(String follower_id, String followed_id) {
public Follow(String follower, String id) {
this.id = new FollowKey(follower, id);
}

public Follow(){

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@

import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public interface FollowRepository extends ReactiveMongoRepository<Follow, Follow.FollowKey> {
@Query("{'id.followed_id': ?0}")
Mono<List<Follow>> findAllByFollowedId(String followed_id);

@Query("{'id.follower_id': ?0}")
Mono<List<Follow>> findAllByFollowerId(String follower_id);
// Mono<Integer> countAllByIdFollowedId(String followed_id);
// Mono<Integer> countAllByIdFollowerId(String follower_id);
@Query("{'_id.followed_id': ?0}")
Flux<Follow> findAllByFollowedId(String followed_id);
@Query("{'_id.follower_id': ?0}")
Flux<Follow> findAllByFollowerId(String follower_id);
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ public Mono<InboxController.UsersFollowResponse> usersFollow(String id,
@RequestParam(required = false)
Integer limit, String followType) {
var items = followType.equals("following") ? followRepository.findAllByFollowerId(id)
.map(list -> list.stream().map(f -> f.id.followed_id).toList()) :
followRepository.findAllByFollowedId(id).map(list -> list.stream().map(f -> f.id.follower_id).toList());
.map(followedUser -> followedUser.id.followed_id).take(limit).collectList() : followRepository.findAllByFollowedId(id)
.map(followerUser -> followerUser.id.follower_id).take(limit).collectList();
String returnID = MothController.BASE_URL + "/users/" + id + followType;
int pageSize = limit != null ? limit : DEFAULT_PAGE_SIZE;
if (page == null) {
Expand Down Expand Up @@ -134,6 +134,13 @@ public Mono<InboxController.UsersFollowResponse> usersFollow(String id,
}
}

public Mono<Follow> saveFollow(String followerId, String followedId) {
Follow follow = new Follow(followerId, followedId);
return followRepository.save(follow);
}



public List<String> paginateFollowers(List<String> followers, int pageNo, int pageSize) {
int startIndex = (pageNo - 1) * pageSize;
int endIndex = Math.min(startIndex + pageSize, followers.size());
Expand All @@ -149,8 +156,8 @@ public Mono<Account> updateAccount(Account a) {

public Mono<SearchResult> filterAccountSearch(String query, Principal user, Boolean following, String max_id,
String min_id, Integer limit, Integer offset, SearchResult result) {
return followRepository.findAllByFollowerId(((Account) user).id).flatMap(f -> {
var followers = f.stream().map(follow -> follow.id.followed_id).collect(Collectors.toSet());
return followRepository.findAllByFollowerId(((Account) user).id).collect(Collectors.toSet()).flatMap(
followers -> {
return accountRepository.findByAcctLike(query)
.filter(account -> following == null || !following || followers.contains(account.id)).take(limit)
.collectList().map(accounts -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import edu.sjsu.moth.generated.QStatus;
import edu.sjsu.moth.generated.SearchResult;
import edu.sjsu.moth.generated.Status;
import edu.sjsu.moth.server.db.AccountField;
import edu.sjsu.moth.server.db.AccountRepository;
import edu.sjsu.moth.server.db.ExternalStatus;
import edu.sjsu.moth.server.db.ExternalStatusRepository;
import edu.sjsu.moth.server.db.Follow;
Expand All @@ -28,6 +30,9 @@ public class StatusService {
@Autowired
StatusRepository statusRepository;

@Autowired
AccountRepository accountRepository;

@Autowired
ExternalStatusRepository externalStatusRepository;

Expand All @@ -38,9 +43,50 @@ public class StatusService {
AccountService accountService;

public Mono<Status> save(Status status) {
return statusRepository.save(status);
// create a Mono that we can tack onto
var mono = Mono.empty();
ArrayList<String> accountsmentioned = new ArrayList<>();
String[] words = status.content.split(" ");
for(String s: words){
if(s.charAt(0) == '@')
accountsmentioned.add(s);
}

// check to see if the post mentions a group account. if it does create a mono for a status post by that group
for(String s : accountsmentioned){
String groupName = s.substring(1);
Mono<Object> finalMono = mono;
// tack the new group post Mono onto mono
mono = mono.then(accountRepository.findItemByAcct(groupName).
flatMap(a ->{
for(AccountField af : a.fields){
if(af.name.equalsIgnoreCase("Group") && af.value.equalsIgnoreCase("True")){
Status groupStatus = new Status(null, status.createdAt, status.inReplyToId, status.inReplyToAccountId, status.sensitive,
status.spoilerText, status.visibility, status.language, status.getUri(), status.getUrl(), status.repliesCount, status.reblogsCount,
status.favouritesCount, status.favourited, status.reblogged, status.muted, status.bookmarked,
status.content, status.reblog, status.application, a,
status.mediaAttachments, status.mentions, status.tags,
status.emojis, status.card, status.poll, status.text, status.edited_at);

return finalMono.then(followRepository.findAllByFollowedId(groupName).collectList().flatMap(list-> {

for(Follow f: list){
if(f.id.follower_id.equals(status.account.id)){
return statusRepository.save(groupStatus).then(Mono.fromRunnable(() -> System.out.println("Gets Executed.....1")));
}
}
return Mono.empty();
}).switchIfEmpty(Mono.fromRunnable(() -> System.out.println("Gets Executed.....2"))));
}
}
return Mono.empty();
}
));
}
return mono.then(statusRepository.save(status));
}


public Mono<ExternalStatus> saveExternal(ExternalStatus status) {
return externalStatusRepository.save(status);
}
Expand Down Expand Up @@ -123,13 +169,9 @@ public Mono<SearchResult> filterStatusSearch(String query, Principal user, Strin

private Flux<Status> filterStatusByViewable(Principal user, Status status, boolean isFollowingTimeline) {
return accountService.getAccount(user.getName())
.switchIfEmpty(Mono.error(new UsernameNotFoundException(user.getName()))).flatMapMany(
acct -> followRepository.findAllByFollowerId(acct.id).defaultIfEmpty(Collections.emptyList())
.map(list -> list.stream().map(f -> f.id.followed_id).toList()).flatMapMany(
followings -> ((status.account.id.equals(acct.id)) ||
(!isFollowingTimeline && status.visibility.equals("public")) ||
followings.contains(status.account.id)) ? Flux.just(status) :
Flux.empty()));
.switchIfEmpty(Mono.error(new UsernameNotFoundException(user.getName())))
.flatMapMany(acct -> followRepository.findAllByFollowerId(acct.id)
.flatMap(following -> ((status.account.id.equals(acct.id)) || (!isFollowingTimeline && status.visibility.equals("public")) || following.id.followed_id.equals(status.account.id)) ? Flux.just(status) : Flux.empty()));
}

}
}

0 comments on commit 2d674e7

Please sign in to comment.