asadasd
This commit is contained in:
parent
6d6fc62af7
commit
2df42dfe17
|
@ -17,6 +17,7 @@ internal class Message {
|
|||
|
||||
public int PositiveVotes { get; init; }
|
||||
public int NegativeVotes { get; init; }
|
||||
public int UserVote { get; set; }
|
||||
|
||||
internal Vector3 Position => new(this.X, this.Y, this.Z);
|
||||
}
|
||||
|
@ -35,6 +36,7 @@ internal class MessageWithTerritory {
|
|||
|
||||
public int PositiveVotes { get; init; }
|
||||
public int NegativeVotes { get; init; }
|
||||
public int UserVote { get; set; }
|
||||
|
||||
internal Vector3 Position => new(this.X, this.Y, this.Z);
|
||||
|
||||
|
@ -48,6 +50,7 @@ internal class MessageWithTerritory {
|
|||
Text = message.Text,
|
||||
PositiveVotes = message.PositiveVotes,
|
||||
NegativeVotes = message.NegativeVotes,
|
||||
UserVote = message.UserVote,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: Orange Guidance Tomestone
|
||||
author: ascclemes
|
||||
punchline: Try finger, but hole
|
||||
punchline: Leave messages like in Souls games. Great chest ahead.
|
||||
description: |-
|
||||
Dark Souls-like messaging system.
|
||||
repo_url: https://git.anna.lgbt/ascclemens/OrangeGuidanceTomestone
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Dalamud.Game;
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Game;
|
||||
using Dalamud.Game.ClientState;
|
||||
using Dalamud.Game.Command;
|
||||
using Dalamud.IoC;
|
||||
|
@ -18,6 +19,9 @@ public class Plugin : IDalamudPlugin {
|
|||
[PluginService]
|
||||
internal CommandManager CommandManager { get; init; }
|
||||
|
||||
[PluginService]
|
||||
internal DataManager DataManager { get; init; }
|
||||
|
||||
[PluginService]
|
||||
internal Framework Framework { get; init; }
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using Dalamud.Utility;
|
||||
using ImGuiNET;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using Newtonsoft.Json;
|
||||
using OrangeGuidanceTomestone.Helpers;
|
||||
|
||||
|
@ -23,10 +25,14 @@ internal class MessageList : ITab {
|
|||
this.MessagesMutex.Wait();
|
||||
|
||||
foreach (var message in this.Messages) {
|
||||
var territory = this.Plugin.DataManager.GetExcelSheet<TerritoryType>()?.GetRow(message.Territory);
|
||||
var territoryName = territory?.PlaceName.Value?.Name?.ToDalamudString().TextValue ?? "???";
|
||||
|
||||
ImGui.TextUnformatted(message.Text);
|
||||
ImGui.TreePush();
|
||||
ImGui.TextUnformatted($"Likes: {message.PositiveVotes}");
|
||||
ImGui.TextUnformatted($"Dislikes: {message.NegativeVotes}");
|
||||
ImGui.TextUnformatted($"Location: {territoryName}");
|
||||
var appraisals = Math.Max(0, message.PositiveVotes - message.NegativeVotes);
|
||||
ImGui.TextUnformatted($"Appraisals: {appraisals} ({message.PositiveVotes} - {message.NegativeVotes}");
|
||||
if (ImGui.Button($"Delete##{message.Id}")) {
|
||||
this.Delete(message.Id);
|
||||
}
|
||||
|
|
|
@ -77,32 +77,50 @@ internal class Viewer {
|
|||
ImGui.TextUnformatted(message.Text);
|
||||
ImGui.PopTextWrapPos();
|
||||
|
||||
ImGui.TextUnformatted($"Appraisals: {message.PositiveVotes - message.NegativeVotes}");
|
||||
var appraisals = Math.Max(0, message.PositiveVotes - message.NegativeVotes);
|
||||
ImGui.TextUnformatted($"Appraisals: {appraisals:N0}");
|
||||
|
||||
if (ImGui.Button("Like")) {
|
||||
void Vote(int way) {
|
||||
Task.Run(async () => {
|
||||
await ServerHelper.SendRequest(
|
||||
var resp = await ServerHelper.SendRequest(
|
||||
this.Plugin.Config.ApiKey,
|
||||
HttpMethod.Patch,
|
||||
$"/messages/{message.Id}/votes",
|
||||
"application/json",
|
||||
new StringContent("1")
|
||||
new StringContent(way.ToString())
|
||||
);
|
||||
|
||||
if (resp.IsSuccessStatusCode) {
|
||||
message.UserVote = way;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var vote = message.UserVote;
|
||||
if (vote == 1) {
|
||||
ImGui.BeginDisabled();
|
||||
}
|
||||
|
||||
if (ImGui.Button("Like")) {
|
||||
Vote(1);
|
||||
}
|
||||
|
||||
if (vote == 1) {
|
||||
ImGui.EndDisabled();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (vote == -1) {
|
||||
ImGui.BeginDisabled();
|
||||
}
|
||||
|
||||
if (ImGui.Button("Dislike")) {
|
||||
Task.Run(async () => {
|
||||
await ServerHelper.SendRequest(
|
||||
this.Plugin.Config.ApiKey,
|
||||
HttpMethod.Patch,
|
||||
$"/messages/{message.Id}/votes",
|
||||
"application/json",
|
||||
new StringContent("-1")
|
||||
);
|
||||
});
|
||||
Vote(-1);
|
||||
}
|
||||
|
||||
if (vote == -1) {
|
||||
ImGui.EndDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,17 +18,6 @@ pub struct Message {
|
|||
pub word_2_word: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct VoteMessage {
|
||||
pub post_id: Uuid,
|
||||
pub vote: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct DeleteMessage {
|
||||
pub post_id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct RetrievedMessage {
|
||||
pub id: String,
|
||||
|
@ -38,6 +27,7 @@ pub struct RetrievedMessage {
|
|||
pub message: String,
|
||||
pub positive_votes: i32,
|
||||
pub negative_votes: i32,
|
||||
pub user_vote: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
|
@ -50,4 +40,5 @@ pub struct RetrievedMessageTerritory {
|
|||
pub message: String,
|
||||
pub positive_votes: i32,
|
||||
pub negative_votes: i32,
|
||||
pub user_vote: i64,
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ mod erase;
|
|||
mod get_location;
|
||||
mod vote;
|
||||
mod get_mine;
|
||||
mod get_message;
|
||||
|
||||
pub fn routes(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
|
||||
register::register(Arc::clone(&state))
|
||||
|
@ -22,6 +23,7 @@ pub fn routes(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
|
|||
.or(write::write(Arc::clone(&state)))
|
||||
.or(erase::erase(Arc::clone(&state)))
|
||||
.or(vote::vote(Arc::clone(&state)))
|
||||
.or(get_message::get_message(Arc::clone(&state)))
|
||||
.or(get_location::get_location(Arc::clone(&state)))
|
||||
.or(get_mine::get_mine(Arc::clone(&state)))
|
||||
.recover(handle_rejection)
|
||||
|
@ -59,6 +61,7 @@ pub enum WebError {
|
|||
InvalidPackId,
|
||||
InvalidIndex,
|
||||
TooManyMessages,
|
||||
NoSuchMessage,
|
||||
}
|
||||
|
||||
impl Reject for WebError {}
|
||||
|
@ -78,6 +81,7 @@ async fn handle_rejection(err: Rejection) -> Result<impl Reply, Infallible> {
|
|||
WebError::InvalidPackId => StatusCode::NOT_FOUND,
|
||||
WebError::InvalidIndex => StatusCode::NOT_FOUND,
|
||||
WebError::TooManyMessages => StatusCode::BAD_REQUEST,
|
||||
WebError::NoSuchMessage => StatusCode::NOT_FOUND,
|
||||
}
|
||||
} else {
|
||||
eprintln!("{:#?}", err);
|
||||
|
|
|
@ -20,7 +20,7 @@ pub fn get_location(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
|
|||
|
||||
async fn logic(state: Arc<State>, id: i64, location: u32) -> Result<impl Reply, Rejection> {
|
||||
// TODO: when we're not just returning all results, make sure own messages are always present
|
||||
let id = location as i64;
|
||||
let location = location as i64;
|
||||
let messages = sqlx::query_as!(
|
||||
RetrievedMessage,
|
||||
// language=sqlite
|
||||
|
@ -31,12 +31,15 @@ async fn logic(state: Arc<State>, id: i64, location: u32) -> Result<impl Reply,
|
|||
m.z,
|
||||
m.message,
|
||||
coalesce(sum(v.vote between 0 and 1), 0) as positive_votes,
|
||||
coalesce(sum(v.vote between -1 and 0), 0) as negative_votes
|
||||
coalesce(sum(v.vote between -1 and 0), 0) as negative_votes,
|
||||
v2.vote as user_vote
|
||||
from messages m
|
||||
left join votes v on m.id = v.message
|
||||
left join votes v2 on m.id = v2.message and v2.user = ?
|
||||
where m.territory = ?
|
||||
group by m.id"#,
|
||||
id,
|
||||
location,
|
||||
)
|
||||
.fetch_all(&state.db)
|
||||
.await
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Context;
|
||||
use uuid::Uuid;
|
||||
use warp::{Filter, Rejection, Reply};
|
||||
use warp::filters::BoxedFilter;
|
||||
|
||||
use crate::message::RetrievedMessageTerritory;
|
||||
use crate::State;
|
||||
use crate::web::{AnyhowRejection, WebError};
|
||||
|
||||
pub fn get_message(state: Arc<State>) -> BoxedFilter<(impl Reply, )> {
|
||||
warp::get()
|
||||
.and(warp::path("messages"))
|
||||
.and(warp::path::param())
|
||||
.and(warp::path::end())
|
||||
.and(super::get_id(Arc::clone(&state)))
|
||||
.and_then(move |message_id: Uuid, id: i64| logic(Arc::clone(&state), id, message_id))
|
||||
.boxed()
|
||||
}
|
||||
|
||||
async fn logic(state: Arc<State>, id: i64, message_id: Uuid) -> Result<impl Reply, Rejection> {
|
||||
let message_id = message_id.simple().to_string();
|
||||
let message = sqlx::query_as!(
|
||||
RetrievedMessageTerritory,
|
||||
// language=sqlite
|
||||
r#"
|
||||
select m.id,
|
||||
m.territory,
|
||||
m.x,
|
||||
m.y,
|
||||
m.z,
|
||||
m.message,
|
||||
coalesce(sum(v.vote between 0 and 1), 0) as positive_votes,
|
||||
coalesce(sum(v.vote between -1 and 0), 0) as negative_votes,
|
||||
v2.vote as user_vote
|
||||
from messages m
|
||||
left join votes v on m.id = v.message
|
||||
left join votes v2 on m.id = v2.message and v2.user = ?
|
||||
where m.id = ?
|
||||
group by m.id"#,
|
||||
id,
|
||||
message_id,
|
||||
)
|
||||
.fetch_optional(&state.db)
|
||||
.await
|
||||
.context("could not get message from database")
|
||||
.map_err(AnyhowRejection)
|
||||
.map_err(warp::reject::custom)?;
|
||||
|
||||
let message = message.ok_or_else(|| warp::reject::custom(WebError::NoSuchMessage))?;
|
||||
Ok(warp::reply::json(&message))
|
||||
}
|
|
@ -29,12 +29,15 @@ async fn logic(state: Arc<State>, id: i64) -> Result<impl Reply, Rejection> {
|
|||
m.z,
|
||||
m.message,
|
||||
coalesce(sum(v.vote between 0 and 1), 0) as positive_votes,
|
||||
coalesce(sum(v.vote between -1 and 0), 0) as negative_votes
|
||||
coalesce(sum(v.vote between -1 and 0), 0) as negative_votes,
|
||||
v2.vote as user_vote
|
||||
from messages m
|
||||
left join votes v on m.id = v.message
|
||||
left join votes v2 on m.id = v2.message and v2.user = ?
|
||||
where m.user = ?
|
||||
group by m.id"#,
|
||||
id,
|
||||
id,
|
||||
)
|
||||
.fetch_all(&state.db)
|
||||
.await
|
||||
|
|
Loading…
Reference in New Issue