Onofficieele HM API Proof of Concept

Status
Niet open voor verdere reacties.
Je moet wat logisch denken ;) maar het is echt niet moeilijk hoor.
Ik heb een voorbeeld van een chat die ongeveer zoals de HM chat eruit ziet gemaakt.
Alles werkt BEHALVE.. de kleur saven (dus zelf een kleur kiezen).. maar dat word nog wel geregeld.
Smilys werken voor het moment ook nog niet, maar daar vind ik wel een makkelijke oplossing voor.

Features:
- Online gebruikers weergeven
- De juiste kleur van de gebruiker laden
- De laatste 5 berichten tonen van de chat

Ik hoop dat ik genoeg comments erbij heb gezet (ben redelijk moe, dus heb dit effe rap op 10min gemaakt)

SOURCE: https://dl.dropboxusercontent.com/u/15707718/HelpMij.nl/HelpmijChat Example 1.zip

die msgbox zit er niet in, maar dan zou je eigenlijk wel moeten kunnen vinden nu ;) If not (kijk dan is bij HandleChatMessages

Btw aan de rest: response over het gebruiksgemak van de api is zeer welkom, voor het moment heb ik nog niet echt een volledige documentatie. Maar deze zou er als volgt komen uit te zien:
http://helpmijapi.t15.org/.net/docs/index.php
(niet up-to-date)

gr,
Maxim
 
Laatst bewerkt:
Nice! Maak er wel een goede documentatie van!

Edit:
Lol, je kunt lege berichten sturen :P
 
Laatst bewerkt:
daantje.. jongen.. dat is niet goed he .. testen moet je rustig doen, en zeker met een beta release van de chat..
Dat gaat niet in goede aard vallen bij mods hoor. :S

Ik denk dat je beter even afstand neemt van de chat.? wat heb je eigenlijk geflikt dat het zo begon?
Loopje gezet op sendmessage ofzo??

Als testen zo gaat begin gaat een Helpmij API/Android app nooit komen he...

gr,
Maxim
 
Laatst bewerkt:
jah, en ben er niet echt blij mee.. Denk ook dat mods er niet blij mee zouden zijn als ze dat zien jong...
Dat word gezien als "ordeverstorende" zaken, en ik ben daar zelf al 2 jaar geleden mee gebanned geweest..
Dit is echt niet goed :S... probeer testen in Stealth mode te doen,. altijd je code debuggen (vooral SendChat enzo) voor je het echt de routine
aanspreekt die het gaat verzenden.

Dit zijn de redenen waarom helpmij geen API wil :S...

PS: n.a.v. de recente gebeurtenissen ga ik een soort Debug omgeving inbouwen in de HelpmijAPI,
die de Helpmij Chat/ Andere functie,.. simuleert
Vervolgens ga ik het maken dat een API zal moeten worden geregistreerd (ergens) voordat deze
op een Real life scenario kan worden toegepast

gr,
Maxim
 
Laatst bewerkt:
Ik heb het eigenlijk helemaal niet bewust gedaan. Ik probeerde er iets in te doen dat de Enter toets ook werkt bij het verzenden van een bericht, maar toen kwamen er ineens heel veel lege berichten.

Edit: Privé berichten worden niet ontvangen. Ik heb ook wat geluidjes toegevoegd :D
 
Laatst bewerkt:
hier wat opmerkingen

naming & conventions
- interfaces beginnen met 'I' - IChat, IGebruiker (verwarrend als interfaces niet met een 'I' beginnen :P)
- getter & setter methods vervangen door properties
- (upper) camel casing toepassen in namespaces
- gebruik van combinatie van nederlands en engels zoals een 'Gebruiker' interface en methods zoals GetUser() of GetBeroep / GetBirthday


wat kleine dingen
- bij UserDataNotFound... mist 'Exception' achter de naam
- bij CredentialsWrongException, WrongCredentialsException leest wat makkelijker (mijn voorkeur zou InvalidCredentialsException zijn)




Omdat er geen properties zijn heb ik zelf 2 classes gemaakt om te databinding op properties te doen.

User:
Code:
using System;
using System.Drawing;
using System.Net;
using mvdw.helpmijapi.gebruiker;

namespace ChatImplementation.Models
{
    public class CustomUser : Gebruiker
    {
        private readonly Gebruiker _source;

        public CustomUser(Gebruiker source)
        {
            _source = source;
        }

        public string Nickname
        {
            get { return _source.GetNickname(); }
            set { _source.SetNickname(value); }
        }

        #region Implementation of Gebruiker Interface (not used)

        public string GetNickname()
        {
            throw new NotImplementedException();
        }

        public void SetNickname(string nickname)
        {
            throw new NotImplementedException();
        }

        public void SetAvatarUrl(string url)
        {
            throw new NotImplementedException();
        }

        public int GetUserID()
        {
            throw new NotImplementedException();
        }

        public void SetUserID(int ID)
        {
            throw new NotImplementedException();
        }

        public string GetSecurityToken()
        {
            throw new NotImplementedException();
        }

        public void SetSecurityToken(string sectoken)
        {
            throw new NotImplementedException();
        }

        public bool IsOnline()
        {
            throw new NotImplementedException();
        }

        public void SetOnline()
        {
            throw new NotImplementedException();
        }

        public void SetOffline()
        {
            throw new NotImplementedException();
        }

        public CookieContainer GetCookies()
        {
            throw new NotImplementedException();
        }

        public void SetCookies(CookieContainer container)
        {
            throw new NotImplementedException();
        }

        public GebruikerData GetUserData(bool fetch)
        {
            throw new NotImplementedException();
        }

        public void SetUserData()
        {
            throw new NotImplementedException();
        }

        public void refreshData()
        {
            throw new NotImplementedException();
        }

        public string GetAvatarUrl()
        {
            throw new NotImplementedException();
        }

        public Image GetAvatar()
        {
            throw new NotImplementedException();
        }

        #endregion

        public override string ToString()
        {
            return Nickname;
        }
    }
}


Message:
Code:
using System;
using System.Drawing;
using mvdw.helpmijapi.chat;
using mvdw.helpmijapi.gebruiker;

namespace ChatImplementation.Models
{
    public class CustomChatMessage : ChatMessage
    {
        private readonly ChatMessage _source;

        public CustomChatMessage(ChatMessage source)
        {
            _source = source;
        }

        public string Sender
        {
            get { return _source.GetUser().GetNickname(); }
        }

        public string Timestamp
        {
            get { return _source.GetTimeStamp().ToShortTimeString(); }
        }

        public string Message
        {
            get { return _source.GetMessage(); }
        }

        public ChatMessageType MessageType
        {
            get { return _source.GetMessageType(); }
        }

        public Color Forecolor
        {
            get
            {
                switch (MessageType)
                {
                    case ChatMessageType.Normal:
                        return Color.Black;
                    case ChatMessageType.Private:
                        return Color.DodgerBlue;
                    case ChatMessageType.Login:
                        return Color.DarkSlateGray;
                    case ChatMessageType.Logout:
                        return Color.DarkSlateGray;
                    case ChatMessageType.Back:
                        return Color.SeaGreen;
                    case ChatMessageType.Away:
                        return Color.Orange;
                    case ChatMessageType.Busy:
                        return Color.Orange;
                    case ChatMessageType.Kicked:
                        return Color.DarkRed;
                    default:
                        return Color.Black;
                }
            }
        }

        #region Implementation of ChatMessage (not used)

        public Gebruiker GetUser()
        {
            throw new NotImplementedException();
        }

        public void SetUser(Gebruiker user)
        {
            throw new NotImplementedException();
        }

        public string GetMessage()
        {
            throw new NotImplementedException();
        }

        public void SetMessage(string message)
        {
            throw new NotImplementedException();
        }

        public Color GetColor()
        {
            throw new NotImplementedException();
        }

        public void SetColor(Color color)
        {
            throw new NotImplementedException();
        }

        public ChatMessageType GetMessageType()
        {
            throw new NotImplementedException();
        }

        public void SetMessageType(ChatMessageType type)
        {
            throw new NotImplementedException();
        }

        public DateTime GetTimeStamp()
        {
            throw new NotImplementedException();
        }

        public void SetTimeStamp(DateTime timestamp)
        {
            throw new NotImplementedException();
        }

        #endregion

        public override string ToString()
        {
            return string.Format("{0} ({1}): {2}", Sender, Timestamp, Message);
        }
    }
}

Ik zal mijn test projectje ook toevoegen later als het handig zou zijn.



Edit:

349895i.png


16gemnd.png


2e3zq0l.png
 
Laatst bewerkt:
Ik heb een toevoeging voor de Verstuur/Send button.
Code:
        private void btnSend_Click(object sender, EventArgs e)
        {
            if (txtMsg.TextLength == 0)
            {
                
            }
            else
            {
                String msg = txtMsg.Text;
                Thread thSend = new Thread(() => SendMessage(msg));
                thSend.Start(); // Zend het bericht naar thread
                txtMsg.Text = ""; // Wis de textbox
                this.ActiveControl = txtMsg; // Zet de textbox weer actief
            }

        }

dit zorgt ervoor dat lege berichten niet verstuurd kunnen worden.
Bug gevonden:

Links worden als html weergegeven.
 
Laatst bewerkt:
Met de if die je daar hebt kun je alsnog lege berichten sturen, in de vorm van een of meerdere spaties.

Als je bijvoorbeeld zoiets als dit doet stuur je altijd iets.
Code:
public void SendMessage(string message)
{
    if (string.IsNullOrWhiteSpace(message)) 
        return;

    Chat.SendMessage(message.Trim());
}

En uiteraard disable je gewoon de button/pressenter als de textbox leeg is.


En links zijn html omdat je deze misschien ook zo wilt weergeven neem ik aan. Als je niet wilt dat je de html ziet kun je deze zelf er uit filteren voordat je deze in de UI laat zien. Anders om moet je misschien zelf ook even een link omzetten naar html zodat hij in de website chat geklikt kan worden (als dit niet vanzelf gebeurt). Heb dit (nog) niet getest.
 
Hallo,

Bedankt voor je voorbeeld Blood ;)
De API Gaat de komende weken waarschijnlijk veel verranderingen ondergaan.
Ik ga proberen een stuk van de api te herschrijven zodat zo veel mogelijk de mobiele site word gebruikt.
Zo gaat alles een pak sneller.

Ook zullen er enkele usercontrols komen die grote delen van de chat nabootsen.

Naamgevingen zullen ook wijzigen, zo is IGebruiker vanaf nu IUser.

Wat ik wel ga laten zijn de Get/Set i.p.v. de properties. Omdat voor vele mensen
properties wat moeilijker te begrijpen is in een api.

gr,
Maxim
 
Ik zou eerst de focus leggen op hoe je wilt dat een gebruiker je API gebruikt. Want dit zal na versie 1.0 eigenlijk niet (of minimaal) meer moeten veranderen (op toevoegingen na). Intern kun je naar hartelust natuurlijk constant wijzigingen doorvoeren.


Voor usercontrols kun je ook gewoon interfaces gebruiken naast je 'internal' controls zodat iedereen zijn eigen versie ervan kan maken zonder veel code te hoeven schrijven, dit wordt dan door de API gedaan.


Namen geven voor al de dingen is altijd wel lastig, persoonlijk hou ik het altijd bij engels.


Voor .NET zijn properties van zelfsprekend, maar in java bestaan deze denk ik niet en zijn er altijd deze apparte get en set methods. Maar zolang de interfaces er zijn kan de gebruiker zijn eigen wrapper class maken omdat deze wel nodig is voor databinding bijvoorbeeld.


Ik zal binnenkort het een en ander eens uitbreiden naar andere dingen dan de chat, daar heb ik nog niet naar gekeken.
 
Ok ik heb een besluit genomen.
Ik ga de komende momenten dat ik aan de API werk, bezig zijn met het herschrijven hiervan.
Deze zou dan direct de volledige versie zijn, omdat de meeste 'moeilijke' dingen al in mijn code staan (werking van de chat, forum ,..)
Ook gaat het met properties, nederlands zijn.

Enkele voorbeelden:

namespace: Helpmij.API
namespace: Helpmij.API.Profiel

Ook zal ik waarschijnlijk de Gebruiker, Chat en ChatMessage naar classen zetten.. Deze waren tot voordien interfaces, maar ik zie niet
echt het nut in om een interface van deze classen te maken? Persoonlijk was het idee om wat meer uitgebreider hierin te gaan: Moderator is een gebruiker maar met extra functies,.. public interface Moderator : Gebruiker .... maar ik ga dit als een classe laten

PS: Er zijn nog veel functies die nog niet optimaal werken buiten de chat.. Gebruiker dinges zoals saven van instellen enzo zouden moeten werken
en het ophalen van titles van topics.
Maar het is nog zeker niet af ;)

Ik ga deze topic nu even met rust laten. Ik weet nu wat ik moet weten met het verder ontwikkelen van de API. (Al bij al was deze
topic voor het proof of concept van de API)

@blood: Is dit ongeveer wat je denk kwa properties en nederlandstalig
Ik heb het op nederlands gehouden, omdat ik vermoed dat er wel wat verwarring kan onstaan in het engels (bv. Gebruiker weet je direct dat het Helpmij is)
maar User is iets dat ook van eender welk ander ding kan zijn (bv. Windows User)
Code:
/*
 * Unofficial Helpmij.nl Aplication Interface
 * Copyright (C) 2009 Maxim Van de Wynckel <Maximvdw> and contributors
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net;
using System.Drawing;

using Helpmij.API.Profiel.Events;

namespace Helpmij.API.Profiel
{
    /// <summary>
    /// Helpmij.nl Gebruiker
    /// </summary>
    public class Gebruiker
    {
        #region Gebruiker Gegevens
        /// <summary>
        /// Gebruikers Identificatie Nummer
        /// </summary>
        int _id = -1;
        /// <summary>
        /// Gebruikersnaam
        /// </summary>
        String _username = "";
        /// <summary>
        /// Gebruikers Status
        /// </summary>
        GebruikerStatus _status = GebruikerStatus.Offline;
        /// <summary>
        /// Gebruiker Session Cookies
        /// </summary>
        CookieContainer _cookies = new CookieContainer();
        /// <summary>
        /// Gebruiker Handtekening
        /// </summary>
        GebruikerHandtekening _signature = new GebruikerHandtekening();
        /// <summary>
        /// Gebruiker Systemen
        /// </summary>
        List<GebruikerSysteem> _systemen = new List<GebruikerSysteem>();
        #endregion


        #region Gebruiker Events
        /// <summary>
        /// Event - Gebruiker Status Wijziging
        /// </summary>
        public event GebruikerStatusEvent onGebruikerStatusChange = null;
        #endregion


        #region Gebruiker Initialize
        /// <summary>
        /// Maak een nieuwe Gebruiker
        /// </summary>
        /// <param name="username">String - Gebruikersnaam</param>
        public Gebruiker(String username)
        {
            // Argumenten opslaan
            _username = username;
        }

        /// <summary>
        /// Log een Gebruiker in
        /// </summary>
        /// <param name="username">String - Gebruikersnaam</param>
        /// <param name="password">String - Wachtwoord</param>
        /// <param name="encrypted">Boolean - Wachtwoord als MD5?</param>
        public Gebruiker(String username, String password, Boolean encrypted)
        {
            // Argumenten opslaan
            _username = username;
        }

        /// <summary>
        /// Verkrijg een Gebruiker op basis van zijn ID
        /// </summary>
        /// <param name="id">int - Gebruiker ID</param>
        public Gebruiker(int id)
        {
            // Argumenten opslaan
            _id = id;
        }
        #endregion

        /// <summary>
        /// Laad de gegevens van een gebruiker
        /// </summary>
        /// <param name="user">Gebruiker - User</param>
        /// <returns>Gebruiker - User</returns>
        public static Gebruiker LaadGegevens(Gebruiker user)
        {
            // Controlleer of het een ingelogde gebruiker is
            if (user.Cookies.Count != 0)
            {
                // Laad prive gegevens

                // Laad publieke gegevens

                return null;
            }
            else
            {
                // Laad publieke gegevens

                return null;
            }
        }


        #region Gebruiker Gegevens
        /// <summary>
        /// Get/Set de Gebruiker ID
        /// </summary>
        public int GebruikerID
        {
            get
            {
                return _id;
            }
            set
            {
                _id = value;
            }
        }

        /// <summary>
        /// Get/Set de Gebruikersnaam
        /// </summary>
        public String Gebruikersnaam
        {
            get
            {
                return _username;
            }
            set
            {
                _username = value;
            }
        }

        /// <summary>
        /// Get/Set de Gebruikers Status
        /// </summary>
        public GebruikerStatus Status
        {
            get
            {
                return _status;
            }
            set
            {
                _status = value;
                if (onGebruikerStatusChange != null)
                {
                    // Invoke event
                    Thread thEvent = new Thread(() => onGebruikerStatusChange(this, new GebruikerStatusArgs(this, _status)));
                    thEvent.Start();
                }
            }
        }

        /// <summary>
        /// Verkrijg de Gebruiker Handtekening
        /// </summary>
        public GebruikerHandtekening Handtekening
        {
            get
            {
                return _signature;
            }
            set
            {
                _signature = value;
            }
        }

        /// <summary>
        /// Get/Set HTTP Cookies
        /// </summary>
        public CookieContainer Cookies
        {
            get
            {
                return _cookies;
            }
            set
            {
                _cookies = value;
            }
        }

        /// <summary>
        /// Get/Set Gebruiker Systemen
        /// </summary>
        public List<GebruikerSysteem> Systemen
        {
            get
            {
                return _systemen;
            }
            set
            {
                _systemen = value;
            }
        }
        #endregion

        #region Override Functies
        /// <summary>
        /// Verkrijg de Gebruikersnaam
        /// </summary>
        /// <returns>String - Gebruikersnaam</returns>
        public override string ToString()
        {
            return _username;
        }
        #endregion
    }
}

gr,
Maxim
 
Laatst bewerkt:
Sorry, ik had je edit niet gezien.


- namespace Helpmij.API.Profiel hier wordt ik blij van :D


- fields hebben geen summary nodig en maakt de code file onnodig vol, zelf zet ik graag initial values in de constructor, maar in fields is niets mis mee


- onGebruikerStatusChange zou ik wijzigen in StatusChanged (hoofdletter in events en je roept hem al aan op de gebruiker dus de extra "Gebruiker" voor StatusChanged is niet nodig lijkt mij, ook de handler)

Code:
public event GebruikerStatusEvent onGebruikerStatusChange = null;
=>
Code:
public event StatusChangedEventHandler StatusChanged;
of generic (1 delegate minder te maken) =>
Code:
public event EventHandler<StatusChangedEventArgs> StatusChanged;


- constructors

ik zie in je constructors een login(user/pass/encrypted) en getUser(id) method? deze zouden in een andere class moeten zitten lijkt mij


- public static Gebruiker LaadGegevens(Gebruiker user) is voor mij wat onduidelijk wat er precies wordt gedaan (laad gegevens is vrij algemeen). De method zit in een gebruiker class, neemt als parameter een gebruiker class en geeft een gebruiker class terug.

zou moeten zien hoe je dit gebruikt, gebruik je dit al in je source? (zal straks eens kijken)


- properties niets op aan te merken op de threaded event notification na?



Uiteindelijk krijg je zelf een manier de voor jou het fijnste werkt, dus het zijn allemaal maar pointers die ik in de loop der tijd ben gaan gebruiken.



p.s. in je licence comment staat Aplication ipv Application
 
hoe gebruik ik deze app? of hoe installeer ik 'm? je bent echt knetter gek goed
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan