diff --git a/db/migrations/15_messages.sql b/db/migrations/15_messages.sql index 121a48b..dc08162 100644 --- a/db/migrations/15_messages.sql +++ b/db/migrations/15_messages.sql @@ -2,8 +2,8 @@ CREATE TABLE messages ( id SERIAL PRIMARY KEY, - from_account_id INTEGER NOT NULL, - to_account_id INTEGER NOT NULL, + from_account_id INTEGER NOT NULL references accounts(id), + to_account_id INTEGER NOT NULL references accounts(id), subject VARCHAR(35) NOT NULL, body VARCHAR(200) NOT NULL, diff --git a/db/migrations/16_friends.sql b/db/migrations/16_friends.sql new file mode 100644 index 0000000..540c212 --- /dev/null +++ b/db/migrations/16_friends.sql @@ -0,0 +1,24 @@ +-- +migrate up + +-- todo: maybe merge this and messages into one? +CREATE TABLE friend_requests ( + id SERIAL PRIMARY KEY, + + from_account_id INTEGER NOT NULL references accounts(id), + to_account_id INTEGER NOT NULL references accounts(id), + + body VARCHAR(140) NOT NULL, + + created_at TEXT NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'now')), + read_at TEXT +); + +CREATE TABLE friend_links ( + account_id_1 INTEGER references accounts(id), + account_id_2 INTEGER references accounts(id), + + created_at TEXT NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'now')) +); + +-- +migrate down +DROP TABLE friend_requests; \ No newline at end of file diff --git a/src/endpoints/social/deleteFriendRequest.cr b/src/endpoints/social/deleteFriendRequest.cr new file mode 100644 index 0000000..c382c4e --- /dev/null +++ b/src/endpoints/social/deleteFriendRequest.cr @@ -0,0 +1,23 @@ +require "uri" + +include CrystalGauntlet + +CrystalGauntlet.endpoints["/deleteGJFriendRequests20.php"] = ->(context : HTTP::Server::Context): String { + params = URI::Params.parse(context.request.body.not_nil!.gets_to_end) + LOG.debug { params.inspect } + + user_id, account_id = Accounts.auth(params) + if !(user_id && account_id) + return "-1" + end + + own_request = params["isSender"]? == "1" + + if DATABASE.scalar("select count(*) from friend_requests where #{own_request ? "to_account_id" : "from_account_id"} = ?", params["targetAccountID"].to_i).as(Int64) == 0 + return "-1" + end + + DATABASE.exec("delete from friend_requests where #{own_request ? "to_account_id" : "from_account_id"} = ?", params["targetAccountID"].to_i) + + return "1" +} diff --git a/src/endpoints/messages/deleteMessage.cr b/src/endpoints/social/deleteMessage.cr similarity index 100% rename from src/endpoints/messages/deleteMessage.cr rename to src/endpoints/social/deleteMessage.cr diff --git a/src/endpoints/social/getFriendRequests.cr b/src/endpoints/social/getFriendRequests.cr new file mode 100644 index 0000000..c70ad16 --- /dev/null +++ b/src/endpoints/social/getFriendRequests.cr @@ -0,0 +1,61 @@ +require "uri" + +include CrystalGauntlet + +requests_per_page = 10 + +CrystalGauntlet.endpoints["/getGJFriendRequests20.php"] = ->(context : HTTP::Server::Context): String { + params = URI::Params.parse(context.request.body.not_nil!.gets_to_end) + LOG.debug { params.inspect } + + user_id, account_id = Accounts.auth(params) + if !(user_id && account_id) + return "-1" + end + + get_sent = params["getSent"]? == "1" + + page_offset = (params["page"]? || "0").to_i * requests_per_page + + requests_count = DATABASE.scalar("select count(*) from friend_requests where #{get_sent ? "from_account_id" : "to_account_id"} = ?", account_id) + + requests = [] of String + + DATABASE.query_each("select friend_requests.id, users.account_id, body, friend_requests.created_at, read_at, users.id, users.username, users.icon_type, users.color1, users.color2, users.cube, users.ship, users.ball, users.ufo, users.wave, users.robot, users.spider, users.special from friend_requests join users on users.id = #{get_sent ? "to_account_id" : "from_account_id"} where #{get_sent ? "from_account_id" : "to_account_id"} = ? limit #{requests_per_page} offset #{page_offset}", account_id) do |rs| + id = rs.read(Int32) + from_account_id = rs.read(Int32) + body = rs.read(String) + created_at = rs.read(String) + read_at = rs.read(String?) + + from_user_id = rs.read(Int32) + username = rs.read(String) + + icon_type = rs.read(Int32) + color1 = rs.read(Int32) + color2 = rs.read(Int32) + + icon_value = [rs.read(Int32), rs.read(Int32), rs.read(Int32), rs.read(Int32), rs.read(Int32), rs.read(Int32), rs.read(Int32)][icon_type] + + special = rs.read(Int32) + + requests << Format.fmt_hash({ + 1 => username, + 2 => from_user_id, + 9 => icon_value, + 10 => color1, + 11 => color2, + 14 => icon_type, + 15 => special, + 16 => from_account_id, + 32 => id, + 35 => Base64.urlsafe_encode(body), + 37 => Time.parse(created_at, Format::TIME_FORMAT, Time::Location::UTC), + 41 => read_at.is_a?(Nil) + }) + end + + searchMeta = "#{requests_count}:#{page_offset}:#{requests_per_page}" + + return requests.join("|") + "#" + searchMeta +} diff --git a/src/endpoints/messages/getMessage.cr b/src/endpoints/social/getMessage.cr similarity index 100% rename from src/endpoints/messages/getMessage.cr rename to src/endpoints/social/getMessage.cr diff --git a/src/endpoints/messages/getMessages.cr b/src/endpoints/social/getMessages.cr similarity index 100% rename from src/endpoints/messages/getMessages.cr rename to src/endpoints/social/getMessages.cr diff --git a/src/endpoints/social/readFriendRequest.cr b/src/endpoints/social/readFriendRequest.cr new file mode 100644 index 0000000..43a3fbc --- /dev/null +++ b/src/endpoints/social/readFriendRequest.cr @@ -0,0 +1,21 @@ +require "uri" + +include CrystalGauntlet + +CrystalGauntlet.endpoints["/readGJFriendRequest20.php"] = ->(context : HTTP::Server::Context): String { + params = URI::Params.parse(context.request.body.not_nil!.gets_to_end) + LOG.debug { params.inspect } + + user_id, account_id = Accounts.auth(params) + if !(user_id && account_id) + return "-1" + end + + if DATABASE.scalar("select count(*) from friend_requests where id = ? and to_account_id = ?", params["requestID"].to_i, account_id).as(Int64) == 0 + return "-1" + end + + DATABASE.exec("update friend_requests set read_at = ? where id = ? and read_at is null", Time.utc.to_s(Format::TIME_FORMAT), params["requestID"].to_i) + + return "1" +} diff --git a/src/endpoints/social/sendFriendRequest.cr b/src/endpoints/social/sendFriendRequest.cr new file mode 100644 index 0000000..e76e5d1 --- /dev/null +++ b/src/endpoints/social/sendFriendRequest.cr @@ -0,0 +1,28 @@ +require "uri" + +include CrystalGauntlet + +CrystalGauntlet.endpoints["/uploadFriendRequest20.php"] = ->(context : HTTP::Server::Context): String { + params = URI::Params.parse(context.request.body.not_nil!.gets_to_end) + LOG.debug { params.inspect } + + user_id, account_id = Accounts.auth(params) + if !(user_id && account_id) + return "-1" + end + + # todo: check for blocks + if DATABASE.scalar("select count(*) from accounts where id = ?", params["toAccountID"].to_i).as(Int64) == 0 + return "-1" + end + + if DATABASE.scalar("select count(*) from friend_requests where from_account_id = ? or to_account_id = ?", account_id).as(Int64) > 0 + # already fr'd + return "-1" + end + + next_fr_id = IDs.get_next_id("friend_requests") + DATABASE.exec("insert into friend_requests (id, from_account_id, to_account_id, body) values (?, ?, ?, ?)", next_fr_id, account_id, params["toAccountID"].to_i, Base64.decode_string(params["comment"])[..140-1]) + + return "1" +} diff --git a/src/endpoints/messages/sendMessage.cr b/src/endpoints/social/sendMessage.cr similarity index 100% rename from src/endpoints/messages/sendMessage.cr rename to src/endpoints/social/sendMessage.cr