mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 08:28:19 +01:00
Add more contribution help
This commit is contained in:
parent
460b68c381
commit
35f54d108f
133
CODE_OF_CONDUCT.md
Normal file
133
CODE_OF_CONDUCT.md
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, caste, color, religion, or sexual
|
||||||
|
identity and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the overall
|
||||||
|
community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or advances of
|
||||||
|
any kind
|
||||||
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email address,
|
||||||
|
without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement at
|
||||||
|
[INSERT CONTACT METHOD].
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series of
|
||||||
|
actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or permanent
|
||||||
|
ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within the
|
||||||
|
community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.1, available at
|
||||||
|
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by
|
||||||
|
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
||||||
|
[https://www.contributor-covenant.org/translations][translations].
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
||||||
|
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||||
|
[FAQ]: https://www.contributor-covenant.org/faq
|
||||||
|
[translations]: https://www.contributor-covenant.org/translations
|
||||||
64
CONTRIBUTING.md
Normal file
64
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
# Contributing to Lysand
|
||||||
|
Thank you for your interest in contributing to Lysand! We welcome contributions from everyone, regardless of their level of experience or expertise.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
To get started, please follow these steps:
|
||||||
|
|
||||||
|
1. Fork the repository, clone it on your local system and make your own branch
|
||||||
|
2. Install the [Bun](https://bun.sh) runtime:
|
||||||
|
```sh
|
||||||
|
curl -fsSL https://bun.sh/install | bash
|
||||||
|
```
|
||||||
|
3. Run `bun install` in the project directory to install the dependencies
|
||||||
|
```sh
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
> You will need a running PostgreSQL database for the next step
|
||||||
|
|
||||||
|
> If you don't have a running PostgreSQL instance, you can use the following `docker-compose.yml` file to start one:
|
||||||
|
> ```yaml
|
||||||
|
>services:
|
||||||
|
> db:
|
||||||
|
> image: postgres:13-alpine
|
||||||
|
> restart: always
|
||||||
|
> init: true
|
||||||
|
> environment: {
|
||||||
|
> POSTGRES_USER: fediproject,
|
||||||
|
> POSTGRES_PASSWORD: fediproject,
|
||||||
|
> POSTGRES_DB: fediproject
|
||||||
|
> }
|
||||||
|
> ports:
|
||||||
|
> - 5432:5432
|
||||||
|
> volumes:
|
||||||
|
> - ./data:/var/lib/postgresql/data
|
||||||
|
> ```
|
||||||
|
|
||||||
|
4. Copy the `config/config.example.toml` file to `config/config.toml` and change the database connection values to your own Postgres instance
|
||||||
|
> For the example above, the values would be:
|
||||||
|
> ```toml
|
||||||
|
> [database]
|
||||||
|
> host = "localhost"
|
||||||
|
> port = 5432
|
||||||
|
> username = "fediproject"
|
||||||
|
> password = "fediproject"
|
||||||
|
> database = "fediproject"
|
||||||
|
> ```
|
||||||
|
5. Fill in the rest of the config file with your own configuration (you can leave most things to the default)
|
||||||
|
|
||||||
|
## Testing your changes
|
||||||
|
|
||||||
|
To start the live server on the address and port specified on the config file, run:
|
||||||
|
```sh
|
||||||
|
bun dev
|
||||||
|
```
|
||||||
|
|
||||||
|
If your port number is lower than 1024, you may need to run the command as root.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
To run the tests, run:
|
||||||
|
```sh
|
||||||
|
bun test
|
||||||
|
```
|
||||||
|
|
||||||
|
The tests are located in the `tests/` directory and follow a Jest-like syntax.
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
# Lysand
|
# Lysand
|
||||||
|
|
||||||
      
|
       [](code_of_conduct.md)
|
||||||
|
|
||||||
|
|
||||||
## What is this?
|
## What is this?
|
||||||
|
|
||||||
|
|
|
||||||
64
classes/activitypub.ts
Normal file
64
classes/activitypub.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { APActivity, APActor } from "activitypub-types";
|
||||||
|
|
||||||
|
export class RemoteActor {
|
||||||
|
private actorData: APActor | null;
|
||||||
|
private actorUri: string;
|
||||||
|
|
||||||
|
constructor(actor: APActor | string) {
|
||||||
|
if (typeof actor === "string") {
|
||||||
|
this.actorUri = actor;
|
||||||
|
this.actorData = null;
|
||||||
|
} else {
|
||||||
|
this.actorUri = actor.id || "";
|
||||||
|
this.actorData = actor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async fetch() {
|
||||||
|
const response = await fetch(this.actorUri);
|
||||||
|
const actorJson = (await response.json()) as APActor;
|
||||||
|
this.actorData = actorJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getData() {
|
||||||
|
return this.actorData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RemoteActivity {
|
||||||
|
private data: APActivity | null;
|
||||||
|
private uri: string;
|
||||||
|
|
||||||
|
constructor(uri: string, data: APActivity | null) {
|
||||||
|
this.uri = uri;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async fetch() {
|
||||||
|
const response = await fetch(this.uri);
|
||||||
|
const json = (await response.json()) as APActivity;
|
||||||
|
this.data = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getData() {
|
||||||
|
return this.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getActor() {
|
||||||
|
if (!this.data) {
|
||||||
|
throw new Error("No data");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(this.data.actor)) {
|
||||||
|
throw new Error("Multiple actors");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof this.data.actor === "string") {
|
||||||
|
const actor = new RemoteActor(this.data.actor);
|
||||||
|
await actor.fetch();
|
||||||
|
return actor.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RemoteActor(this.data.actor as any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -223,7 +223,7 @@ export class Status extends BaseEntity {
|
||||||
id: `${config.http.base_url}/users/${data.account.username}/statuses/${newStatus.id}`,
|
id: `${config.http.base_url}/users/${data.account.username}/statuses/${newStatus.id}`,
|
||||||
type: "Note",
|
type: "Note",
|
||||||
summary: data.spoiler_text,
|
summary: data.spoiler_text,
|
||||||
content: data.content, // TODO: Format as HTML
|
content: data.content,
|
||||||
inReplyTo: data.reply?.object
|
inReplyTo: data.reply?.object
|
||||||
? data.reply.object.data.id
|
? data.reply.object.data.id
|
||||||
: undefined,
|
: undefined,
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,8 @@ export class User extends BaseEntity {
|
||||||
* Fetches the list of followers associated with the actor and updates the user's followers
|
* Fetches the list of followers associated with the actor and updates the user's followers
|
||||||
*/
|
*/
|
||||||
async fetchFollowers() {
|
async fetchFollowers() {
|
||||||
|
const config = getConfig();
|
||||||
|
|
||||||
let followers: APOrderedCollectionPage = await fetch(
|
let followers: APOrderedCollectionPage = await fetch(
|
||||||
`${this.actor.data.followers?.toString() ?? ""}?page=1`,
|
`${this.actor.data.followers?.toString() ?? ""}?page=1`,
|
||||||
{
|
{
|
||||||
|
|
@ -234,7 +236,10 @@ export class User extends BaseEntity {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: integrate followers
|
if (config.activitypub.fetch_all_collection_members) {
|
||||||
|
// Loop through followers list and retrieve each actor individually
|
||||||
|
// TODO: Implement
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
49
server/api/api/v1/statuses/[id]/context.ts
Normal file
49
server/api/api/v1/statuses/[id]/context.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { applyConfig } from "@api";
|
||||||
|
import { errorResponse, jsonResponse } from "@response";
|
||||||
|
import { MatchedRoute } from "bun";
|
||||||
|
import { RawObject } from "~database/entities/RawObject";
|
||||||
|
import { Status } from "~database/entities/Status";
|
||||||
|
import { User } from "~database/entities/User";
|
||||||
|
import { APIRouteMeta } from "~types/api";
|
||||||
|
|
||||||
|
export const meta: APIRouteMeta = applyConfig({
|
||||||
|
allowedMethods: ["GET"],
|
||||||
|
ratelimits: {
|
||||||
|
max: 100,
|
||||||
|
duration: 60,
|
||||||
|
},
|
||||||
|
route: "/api/v1/statuses/:id/context",
|
||||||
|
auth: {
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch a user
|
||||||
|
*/
|
||||||
|
export default async (
|
||||||
|
req: Request,
|
||||||
|
matchedRoute: MatchedRoute
|
||||||
|
): Promise<Response> => {
|
||||||
|
// Public for public statuses limited to 40 ancestors and 60 descendants with a maximum depth of 20.
|
||||||
|
// User token + read:statuses for up to 4,096 ancestors, 4,096 descendants, unlimited depth, and private statuses.
|
||||||
|
const id = matchedRoute.params.id;
|
||||||
|
|
||||||
|
const { user } = await User.getFromRequest(req);
|
||||||
|
|
||||||
|
let foundStatus: RawObject | null;
|
||||||
|
try {
|
||||||
|
foundStatus = await RawObject.findOneBy({
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
return errorResponse("Invalid ID", 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundStatus) return errorResponse("Record not found", 404);
|
||||||
|
|
||||||
|
// Get all ancestors
|
||||||
|
const ancestors = await foundStatus.getAncestors();
|
||||||
|
|
||||||
|
return jsonResponse({});
|
||||||
|
};
|
||||||
|
|
@ -71,7 +71,16 @@ export default async (
|
||||||
// Delete status and all associated objects
|
// Delete status and all associated objects
|
||||||
await status.object.remove();
|
await status.object.remove();
|
||||||
|
|
||||||
return jsonResponse({}, 200);
|
return jsonResponse(
|
||||||
|
{
|
||||||
|
...(await status.toAPI()),
|
||||||
|
// TODO: Add
|
||||||
|
// text: Add source text
|
||||||
|
// poll: Add source poll
|
||||||
|
// media_attachments
|
||||||
|
},
|
||||||
|
200
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonResponse({});
|
return jsonResponse({});
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ export interface ConfigType {
|
||||||
discard_follows: string[];
|
discard_follows: string[];
|
||||||
force_sensitive: string[];
|
force_sensitive: string[];
|
||||||
remove_media: string[];
|
remove_media: string[];
|
||||||
fetch_all_colletion_members: boolean;
|
fetch_all_collection_members: boolean;
|
||||||
authorized_fetch: boolean;
|
authorized_fetch: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -244,7 +244,7 @@ export const configDefaults: ConfigType = {
|
||||||
discard_updates: [],
|
discard_updates: [],
|
||||||
discard_follows: [],
|
discard_follows: [],
|
||||||
remove_media: [],
|
remove_media: [],
|
||||||
fetch_all_colletion_members: false,
|
fetch_all_collection_members: false,
|
||||||
authorized_fetch: false,
|
authorized_fetch: false,
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue